【问题标题】:Does django cache model data between queries?django 是否在查询之间缓存模型数据?
【发布时间】:2014-10-30 13:45:42
【问题描述】:

我正在使用 django 1.6,mysql 5.6 作为带有 innodb 表的数据库。 Debug 在我的设置文件中设置为 false。

在一个脚本中,我循环遍历一个元素列表,检查它是否已经存在于db中,如果不存在则创建,如下:

for item in list:
    try:
        MyModel.objects.get(field=item)
    except MyModel.DoesNotExist:
        MyModel.objects.create(field=item)

我希望只有当它不存在时才会在数据库中创建一个项目,但这种方法会创建具有相同字段值的多个项目。这里似乎有某种缓存。

这里有两个问题;

如何更改此行为,以便在每次循环运行时检查数据库的最新状态是否存在?

这种行为是否与我通过脚本运行有关?如果相同的循环将在视图中运行。行为会有什么不同吗?

编辑:

我已经通过类似问题的建议将事务隔离更改为 READ-COMMITTED 。这会导致常规 Django 视图操作的性能下降吗?

【问题讨论】:

  • 事务应该不是问题,除非你的数据库在别处被修改,你能发布你的模型定义和你的“项目”类型吗?
  • 围绕你的 sn-p 的一些更完整的代码可能会有所帮助。这是在transaction.atomic() 内运行吗? (另外,如果您只想为每个 field=item 设置一个,您可能应该让 field 唯一。)

标签: django caching django-models race-condition


【解决方案1】:

您似乎在这里遇到了竞争条件。如果你看一下 Django 原生为你提供的 get_or_create 代码,它看起来和你的很相似

try:
   obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
   obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
obj.save()

事实上,上面的代码也可能会受到竞争条件的影响,并创建比documentation 也说的对象更多的对象:However, if uniqueness is not enforced at the database level for the kwargs used in a get_or_create call (see unique or unique_together), this method is prone to a race-condition which can result in multiple rows with the same parameters being inserted simultaneously.

因此,在这种情况下,您的解决方案是使 field 独一无二。

或者,如果该字段不能是唯一的,我建议您尝试明确地使用 transactions

from django.db import transaction 

with transaction.atomic():
    # do_database_stuff

【讨论】:

    【解决方案2】:

    使字段唯一

    #your model
    class MyModel(models.Model):
          field = modesl.IntegerField(unique=True)
    
          def __unicode__(self):
              return '%s' % self.field
    
    
    """your code to interac with the model (Don't matther where you have this code 
    (in the view, or elsewhere)), the behavior of the code is going to be the same. 
    views.py just is a python file."""
    
    from you_app.models import MyModel
    from django.db import IntegrityError
    
    def insert_item(list_item):
        for item in list_item:
            try:
                itemobj = MyModel.objects.create(field=item)
            except IntegrityError:
                #exists, posible you want to make some update here
                itemobj = MyModel.objects.get(field=item)
                #maybe update...
            else:
                #do whatevert you want with itemobj
                print itemobj
    

    【讨论】:

      猜你喜欢
      • 2010-11-22
      • 2021-01-05
      • 2012-08-16
      • 2018-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 2010-10-29
      相关资源
      最近更新 更多