Hello,

I want after a user request to be sure that certain objects are stored in a Postgres database, even if before the request some of the objects were there.

The only way I can do this with django, not talking about raw sql, is with "for obj in objects: Model.objects.get_or_create(obj)". It works, but creates several INSERTs, and is hence suboptimal.

I cannot use bulk_create(), which squeezes all the INSERTs to a single one, as it does not work, if any of the to-be-inserted rows was already in the database.

In Postgresql this can be achieved by sending "INSERT ... ON CONFLICT DO NOTHING".

I propose changing the interface of QuerySet.bulk_create to accept one more parameter on_conflict, that can be a string e.g. "DO NOTHING" or Q-objects (which could be used to implement ON CONFLICT DO UPDATE SET ... WHERE ...

def bulk_create(self, objs, batch_size=None, on_conflict=None): ...

What are the arguments against or in favour?

The further, bulk_create() does not send post_save signal, because it is difficult to implement with the standard backends, except with postgresql.

I propose extending the implementation to send the signal:

https://code.djangoproject.com/ticket/28641#comment:1

when Postgresql is used. I assume there a no users, who want to get a (post_save) signal on save() but not on bulk_create().

Combining ON CONFLICT DO NOTHING with sending post_save gets however nasty, as "INSERT ... ON CONFLICT DO NOTHING RETURNING id;" does not return anything on unchanged rows, hence the system knows at the end how much rows were changed, but not which, so it cannot determine for which objects to send post_save. At least I have not found a way how to figure out which rows were inserted/not inserted.

However, this can be achieved by RETURNING * and then comparing the returned objects to the sent objects, eventually making bulk_create() return the objects actually inserted in the database.

These changes will allow a switch to a single INSERT on Postgresql.

Regards
  Дилян

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/daa88462-c095-dfcc-2ce7-6d34f6bbc2f6%40aegee.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to