jia Jimmy
jia Jimmy

Reputation: 1848

How to add record after bulk_create objs in django?

I want to add a record for each model object that created by bulk_create method of django, how can I make it work?

It seems rewriting save method of model doesn't work.

# WarningAccountsSpend
class WarningAccountsSpend(models.Model):
    account_id = models.CharField(max_length=32, blank=True, null=True)
    date = models.IntegerField(blank=True, null=True)
    account_type = models.IntegerField(blank=True, null=True)
    entity = models.CharField(max_length=255, blank=True, null=True)
    spend_cap = models.BigIntegerField(db_column='spend cap', blank=True, null=True)  # Field renamed to remove unsuitable characters.
    balance = models.BigIntegerField(blank=True, null=True)
    is_spend_over_yesterday = models.IntegerField(blank=True, null=True)
    growth_rate = models.IntegerField(blank=True, null=True)
    account_create_time = models.DateTimeField(blank=True, null=True)
    is_violated = models.IntegerField(blank=True, null=True)
    note = models.CharField(max_length=255, blank=True, null=True)
    created_time = models.DateTimeField(blank=True, null=True)
    spend = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'warning_accounts_spend'
        unique_together = (('account_id', 'date'),)
        ordering = ["-spend"]

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        # add operate log 
        # It seems not work here
        super(WarningAccountsSpend, self).save(force_insert=False, force_update=False, using=None,
             update_fields=None)

# bulk_create model obj

WarningAccountsSpend.objects.bulk_create([...], ignore_conflicts=True)

How can I add some other operation for object that I bulk created.

Update my trial so far

I override _insert and update method of class Queryset which is the basic operation for bulk_create and bulk_update.

It worked but _insert itself is a private method. So my trial seems not to be good. Any better way to make this?

Great thanks.

from django.db import models
from django.db.models.manager import BaseManager
from django.db.models.query import QuerySet



class AddLogQuerySet(QuerySet):
    def _insert(self, objs, fields, return_id=False, raw=False, using=None, ignore_conflicts=False):
        # bulk_create base operation
        obj_id = super(AddLogQuerySet, self)._insert(objs, fields, return_id=True, raw=raw, using=using, ignore_conflicts=ignore_conflicts)
        if obj_id != 0:
            # add add record for each obj created by bulk_create
            ...

    def update(self, **kwargs):
        # bulk_update base operation
        # add add record for each obj updated by bulk_update        
        ...


class AddLogManager(BaseManager.from_queryset(AddLogQuerySet)):
    ...


class WarningAccountsSpend(models.Model):
    account_id = models.CharField(max_length=32, blank=True, null=True)
    date = models.IntegerField(blank=True, null=True)
    account_type = models.IntegerField(blank=True, null=True)
    entity = models.CharField(max_length=255, blank=True, null=True)
    spend_cap = models.BigIntegerField(db_column='spend cap', blank=True, null=True)  # Field renamed to remove unsuitable characters.
    balance = models.BigIntegerField(blank=True, null=True)
    is_spend_over_yesterday = models.IntegerField(blank=True, null=True)
    growth_rate = models.IntegerField(blank=True, null=True)
    account_create_time = models.DateTimeField(blank=True, null=True)
    is_violated = models.IntegerField(blank=True, null=True)
    note = models.CharField(max_length=255, blank=True, null=True)
    created_time = models.DateTimeField(blank=True, null=True)
    spend = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True)

    objects = AddLogManager()

    class Meta:
        managed = False
        db_table = 'warning_accounts_spend'
        unique_together = (('account_id', 'date'),)
        ordering = ["-spend"]

    
    # save and update operation for single obj created or updated
    def save(self, user_id, log_type, force_insert=False, force_update=False, using=None,
             update_fields=None):

        obj_id = self.pk
        origin_obj = ...

Upvotes: 0

Views: 859

Answers (1)

gunsodo
gunsodo

Reputation: 175

This is mentioned in django's documentation. You don't have to call save() to update your database.

The model’s save() method will not be called, and the pre_save and post_save signals will not be sent.

After you call bulk_create(), all the records will be saved to the database, if you want to update some fields please see bulk_update() in the documentation link attached above.

Upvotes: 1

Related Questions