【问题标题】:Efficient way of avoiding adding duplicate entries to Django model避免向 Django 模型添加重复条目的有效方法
【发布时间】:2020-08-09 06:27:09
【问题描述】:

我已经阅读了很多关于如何在 Django 中使数据库/模型独一无二的文章,而且这些文章似乎都有效。但是,我没有看到任何帖子讨论避免向数据库添加重复条目的有效方法。

我的模型如下所示:

# from app.models
class TestModel(models.Model):
    text = models.TextField(unique=True, null=True)
    fixed_field = models.TextField()

我目前避免添加重复条目而不会出错的方法如下。

# from app.views
posts = ["one", "two", "three"]
fixed_field = "test"

for post in posts:
    try:
        TestModel(text=post, fixed_field = fixed_field).save()
    except IntegrityError:
        pass

如果我不这样做,我会得到一个 IntegrityError。有什么办法可以提高效率吗?

【问题讨论】:

    标签: python django


    【解决方案1】:

    如果您要批量添加项目,您可以首先尝试阻止添加这些项目,方法是获取需要唯一的文本,然后制作一个不引入重复的TestModels 列表:

    used_text = set(TestModel.objects.values_list('text', flat=True))
    
    posts = ['one', 'two', 'three']
    fixed_field = "test"
    
    test_models = []
    for post in posts:
        if post not in used_text:
            used_text.add(post)
            test_models.add(TestModel(text=post, fixed_field = fixed_field))
    
    test_models.objects.bulk_create(test_models)

    .bulk_create(..) [Django-doc] 然后批量创建所有记录,通常在一个查询中。如果多个查询元素数量巨大,但每次查询都会插入大量记录。

    但由于竞争条件,上述操作仍然会失败,因为在获取数据库中的texts 和添加新的之间,其他查询可以更新数据库的状态,所以尽管可能性不大,但您可能应该使用重试机制,再次从列表中过滤掉 TestModels,并尝试重新插入这些内容。

    【讨论】:

    • 非常感谢您的回复。就我自己的直觉而言,我目前的解决方案是“种族条件证明”,对吧?虽然我可以想象它比正确实施某种重试机制要慢。
    • @MennoVanDijk:如果数据库是竞争条件证明,是的:),尽管如果您要插入大量项目(1000+),则需要一些时间,因为您每次往返于数据库。如果数据库不经常修改(因此不太可能发生冲突),那么通常批量插入会更快。当然,如果 并发 插入的数量非常多,那么最终你可能会不断重试插入,并且每次都失败。
    • 好吧,对于 webdev 来说非常新,所以仍在寻找解决此类相当琐碎问题的最佳实践方法。谢谢你的建议,我会看看我是否能在适当的时候找到合适的解决方案。
    猜你喜欢
    • 2021-09-08
    • 1970-01-01
    • 2011-03-04
    • 2023-03-09
    • 2017-12-27
    • 2016-11-22
    • 1970-01-01
    • 2012-08-24
    相关资源
    最近更新 更多