I recently had occasion to lazily use the Django “get_or_create” convenience method to instantiate some database ORM records. This worked fine the first time through, and I didn’t have to write the tedious “query, check, then insert” rigamarole. So far so good. These were new records so the “or_create” part was operative.
Then, while actually testing the “get_” part by running over the same input dataset, I noticed it was nearly as slow as the INSERTs, even though it should have been doing indexed SELECTs over a modest, in-memory table. Odd. I checked the debug output from Django and discovered that get_or_create was invoking UPDATE calls.
The only field it was updating was:
updated_at = models.DateTimeField(auto_now=True)
Thanks, Django. You just created a tautological truth. It was updated at that datetime because … you updated it at that datetime.
Interestingly, its sister field did NOT get updated:
created_at = models.DateTimeField(auto_now_add=True, editable=False)
This field, true to its args, was not editable, even by whatever evil gnome was going around editing the updated_at field.
Recommendation: if you want actual timestamps in your database, why don’t you use a real database and put a trigger on it? ORM-layer nonsense is a surefire way to have everything FUBAR as soon as someone drops to raw SQL for performance or clarity.