fopina / django-bulk-update-or-create

`bulk_update_or_create` for Django model managers
MIT License
148 stars 16 forks source link

How can I bulk_update_or_create with ManyToManyField? #29

Open Su-yj opened 2 years ago

fopina commented 1 year ago

You can't, same as with bulk_create, bulk_update or even with normal .save()

You can however use the callback or the returned objects to update those fields after.

I'll add example to documentation as I just noticed there is none using callback / returned objects, just need to finish #37 first

Su-yj commented 1 year ago

You can't, same as with bulk_create, bulk_update or even with normal .save()

You can however use the callback or the returned objects to update those fields after.

I'll add example to documentation as I just noticed there is none using callback / returned objects, just need to finish #37 first

Maybe I can use callback, but the data returned by the callback function cannot find relationship with original data.

My code likes this:

def callback(ret):
    created, updated = ret
    ...

with RandomData.objects.bulk_update_or_create_context(update_fields=['data'], match_field='uuid', batch_size=10, status_cb=callback) as bulkit:
    for item in origin_data:
        bulkit.queue(RandomData(id=item['id'], data=item['data']))
fopina commented 1 year ago

Indeed, you’ll have to keep track of that matching somewhere. I’ve done in before using the same unique field of each record as a dict key and a list of related objects as value.

Not an issue in this package though as none django ORM handles creating relationships. You always create them after creating the object.

Su-yj commented 1 year ago

Indeed, you’ll have to keep track of that matching somewhere. I’ve done in before using the same unique field of each record as a dict key and a list of related objects as value.

Not an issue in this package though as none django ORM handles creating relationships. You always create them after creating the object.

Yes. I know i can keep a track to do that. But I think it`s not pythoning.

I have a idea. Can the bulkit queue accept the second param? Then, the callback function return a new model and param which passed in by the user. User can get the data without the track.

Just like this:

with RandomData.objects.bulk_update_or_create_context(update_fields=['data'], match_field='uuid', batch_size=10, status_cb=callback) as bulkit:
    for item in origin_data:
        # put the data to queue
        bulkit.queue(RandomData(id=item['id'], data=item['data']), param=item)

def callback(ret):
    created, updated = ret
    for model, data in created:
        pass
    ...

It just my think. It may not be easy to realize, and will destroy the previous interface.

fopina commented 1 year ago

It’s not an uncommon for methods with callbacks to allow for passing extra context, it’s not a bad idea.

and I think the change can be retro compatible as context will be an optional kwarg and it can be sent to callback only if defined.

I’ll keep it in mind, thanks!