Force update of an existing model

I have the following model which automatically generates a code on save.

class CodeVerify(models.Model):
    email = models.EmailField(blank=False, null=False, unique=True)
    code = models.CharField(max_length=6, blank=True, null=True)
    time_stamp = models.DateTimeField(auto_now=True)

    def save(self, *args, **kwargs):
        self.code = generate_code()
        super(CodeVerify, self).save(*args, **kwargs)

    def __str__(self):
        return str(self.code)

I am trying to find the best way updating an existing record so that both time_stamp and code fields are updated.

I have tried a couple of working options, but they feel a little ‘hackish’, as follows:
(assuming that there is an existing record ‘example@email.com’

code_verify, created = CodeVerify.objects.update_or_create(email='example@email.com', defaults={'email':'example@email.com'})
and;
code_verify, created = CodeVerify.objects.update_or_create(email='example@email.com', defaults={'code':''})

Is there a better way?

Depending upon the architecture of your system and what methods you use to update the data, you might want to consider using a database trigger for this.

The issue with relying upon the save method is that there are many ways a table can be updated without causing the save method to be called. (e.g. bulk_update)

This means you need to decide:

  • Does there need to be a solid guarantee that those fields will be updated any time the model is updated?
  • Does there need to be a guarantee that the code field is only updated when some other field is changed?
  • Is there sufficient control over how that table or model is updated to ensure that only methods that call the save method are used?

So this is one of those issues that need to be looked at in the context of the overall system requirements.

If the pure-Django method is considered adequate, then just calling save on the desired instance is sufficient. I’m not sure what you’re trying to accomplish with using the update_or_create function. What benefit do you think that provides?

Hi Ken, Many thanks for your reply.

Yes, definitely.

Both ‘code’ and ‘time_stamp’ fields need to be changed on each ‘update’. I am using update as a means to trigger the generate_code() for the code field and auto_now for the time_stamp field.

Yes, the sole purpose of the CodeVerify model is to store email verification parameters after which the information is redundant. I intend to implement a cleanup of orphaned records via a daily ‘time_stamp expiration’ using celery.

All I am trying to do is look for an existing record, and if it exists, then trigger an update of the code and time_stamp fields via the save() method, or, if it doesn’t exist, create a new record.

Ok, if you need a solid guarantee, then create a database trigger.

If you’re willing to accept that there are circumstances where the table can be updated without those values being changed, then yes, either save or update_or_create will do that for you.

There may be other (more verbose) ways that more explicitly shows what the intent is, but I wouldn’t necessarily describe them as “better”.

Many thanks Ken.

Do you have a link to a reliable guide database trigger on how to implement database triggers?

Django has no direct facilities for creating triggers. You can either define them directly in the database or you can add a custom migration to run the necessary SQL statement(s).

If you’re using PostgreSQL, then their docs are a good place to start. There are a bunch of examples at the end of the page.

See PostgreSQL: Documentation: 15: CREATE TRIGGER

Note, this also implies that you will want to implement your generate_code function in the database as well.

Ken, many thanks once again for your help.