Does django cache model data between requests?

I am using django 1.6, with mysql 5.6 as my database with innodb tables. Debug is set to false in my settings file.

Inside the script, I loop through the list of items, check if it exists in the db, and create if it doesn't exist like this:

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

      

I expect this to create an item in the db only if it doesn't exist, but this approach creates multiple items with the same field value. There seems to be some kind of caching going on here.

I have two questions here:

How can I change this behavior to check for existence from the last state of the db in each loop run?

Is it related to this behavior with a script? If the same loop will run inside the view. will the behavior be any different?

EDIT:

I came up with suggestions on a similar question to change transaction isolation to READ-COMMITTED. Wouldn't this lead to performance disadvantages in Django's regular actions?

+3


source to share


2 answers


You seem to be running into a race condition here. If you look at the code for get_or_create that Django provides you initially, it is similar to yours.

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()

      

In fact, the above code can also be subject to a race condition and create more objects than the one that the documentation also says: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.



Thus, the solution for you makes it field

unique in this case.

Or if the field cannot be unique, I suggest you try with transactions explicitly.

from django.db import transaction 

with transaction.atomic():
    # do_database_stuff

      

+3


source


make the field unique



#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

      

+1


source







All Articles