Search code examples
pythondjangocitus

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?


Solution

  • 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