synic synic - 4 months ago 18
Python Question

Django - NEVER update a column when saving

I am trying to use citus data (https://www.citusdata.com/) with Django.

Most everything is working so far, except trying to

save
a model that has already been saved:

NotSupportedError: modifying the partition value of rows is not allowed


This is because django always includes every single field in the update SQL, even if that field has not changed.

In Citus, you must pick a field to be your partitioning field, and then you cannot change it. So, when I'm saving an object, it doesn't like that the partition key is in the update statement, even if it didn't change.

I know that you can pass the
update_fields
keyword arg to the
save
method, but I'm wondering if I can somehow tell django to NEVER include a field when updating?

Answer

Django does not provide this functionality "out of the box". You could override the save method of your class to set all fields other than your partition field as the value for update_fields

def save(self, **kwargs):
    kwargs.setdefault('update_fields', ['field1', 'field2'])
    return super(Class, self).save(**kwargs)

A more dynamic option, if you do not want to update this method everytime you change the fields of your class, would be to use the Meta API to get all fields of the class and exclude your partition field

def save(self, **kwargs):
    kwargs.setdefault(
        'update_fields',
        [f.name for f in self.__class__._meta.get_fields() if f.name != 'partition_field']
    )
    return super(Class, self).save(**kwargs)

There are several other methods by which Django will attempt to update your models. Maybe a base class that all your models inherit from that implement these methods would work

Comments