Denzo
Denzo

Reputation: 431

Django's Model save flow

I noticed that there's no guarantee that the data base is updated synchronously after calling save() on a model.

I have done a simple test by making an ajax call to the following method

def save(request, id)
  product = ProductModel.objects.find(id = id)
  product.name = 'New Product Name'
  product.save()

  return HTTPResponse('success')

On the client side I wait for a response from the above method and then execute findAll method that retrieves the list of products. The returned list of products contains the old value for the name of the updated product.

However, if I delay the request for the list of products then it contains the new value, just like it is should.

This means that return HTTPResponse('success') if fired before the new values are written into the data base.

If the above is true then is there a way to return the HTTP response only after the data base is updated.

Upvotes: 4

Views: 2725

Answers (2)

Daniel Roseman
Daniel Roseman

Reputation: 599628

You should have mentioned App Engine more prominently. I've added it to the tags.

This is very definitely because of your lack of understanding of GAE, rather than anything to do with Django. You should read the GAE documentation on eventual consistency in the datastore, and structure your models and queries appropriately.

Normal Django, running with a standard relational database, would not have this issue.

Upvotes: 5

Alex Parakhnevich
Alex Parakhnevich

Reputation: 5172

The view should not return anything prior to the .save() function ends its flow.

As for the flow itself, the Django's docs declare it quite explicitly:

When you save an object, Django performs the following steps:

1) Emit a pre-save signal. The signal django.db.models.signals.pre_save is sent, allowing any functions listening for that signal to take some customized action.

2) Pre-process the data. Each field on the object is asked to perform any automated data modification that the field may need to perform.

Most fields do no pre-processing — the field data is kept as-is. Pre-processing is only used on fields that have special behavior. For example, if your model has a DateField with auto_now=True, the pre-save phase will alter the data in the object to ensure that the date field contains the current date stamp. (Our documentation doesn’t yet include a list of all the fields with this “special behavior.”)

3) Prepare the data for the database. Each field is asked to provide its current value in a data type that can be written to the database.

Most fields require no data preparation. Simple data types, such as integers and strings, are ‘ready to write’ as a Python object. However, more complex data types often require some modification.

For example, DateField fields use a Python datetime object to store data. Databases don’t store datetime objects, so the field value must be converted into an ISO-compliant date string for insertion into the database.

4) Insert the data into the database. The pre-processed, prepared data is then composed into an SQL statement for insertion into the database.

5) Emit a post-save signal. The signal django.db.models.signals.post_save is sent, allowing any functions listening for that signal to take some customized action.

Let me note that the behaviour you're receiving is possible if you've applied @transaction.commit_on_success decorator to your view, though, I don't see it in your code.
More on transactions: https://docs.djangoproject.com/en/1.5/topics/db/transactions/

Upvotes: 2

Related Questions