3

I have a Django model that looks like this:

class LocationMaster(models.Model):
    id = models.AutoField(primary_key=True)
    open_date = models.DateField(blank=True, null=True)
    months_open = models.DecimalField(max_digits=18, decimal_places=2, blank=True, null=True) # Calculated column in SQL Server
    maturity = models.CharField(max_length=50, blank=True) # Calculated column in SQL Server

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        # ?? Something here
        super(LocationMaster, self).save(force_insert, force_update, using, update_field)

Two of my columns are SQL Server computed columns. I would like to display these columns in my application, including in the admin, but not insert or update these columns since they are computed. Without modified my model, I get this error:

('42000', '[42000] [FreeTDS][SQL Server]The column "months_open" cannot be modified because it is either a computed column or is the result of a UNION operator. (271) (SQLExecDirectW)')

How do I modify my model so that Django does not attempt to insert or update these specific columns?

duffn
  • 3,690
  • 8
  • 33
  • 68

3 Answers3

4

I went with this work around in the save method to ignore the computed SQL Server columns. Found here: Prevent Django from updating identity column in MSSQL

def save(self, force_insert=False, force_update=False, using=None,
         update_fields=None):
    # Hack to not save the maturity and months_open as they are computed columns
    self._meta.local_fields = [f for f in self._meta.local_fields if f.name not in ('maturity', 'months_open')]
    super(LocationMaster, self).save(force_insert, force_update, using, update_fields)
Community
  • 1
  • 1
duffn
  • 3,690
  • 8
  • 33
  • 68
4

I encountered this issue when a field is updated with PostgreSQL triggers, but django overwrites it's value (in same transaction).

This is a generic class decorator that prevents sending enabled=False fields to database (perhaps in any query, like UPDATE).

def prevent_updating_non_editable_fields(clazz):
      """ prevents sending non`editable` fields in queries  """
      meta = clazz._meta
      meta.local_concrete_fields = [f for f in meta.local_concrete_fields if f.editable]
      return clazz


@prevent_updating_editable_fields
class MyModel(models.Model):
       precomputed = models.IntegerField(default=0, editable=False)
Taha Jahangir
  • 4,774
  • 2
  • 42
  • 49
-3

You should be able to accomplish this by adding editable=False to the field.

More info here: https://docs.djangoproject.com/en/dev/ref/models/fields/#editable

Abid A
  • 7,588
  • 4
  • 32
  • 32
  • 1
    Thanks for the answer, but that does not appear to work. I have added "editable=False" to both fields, but still received the same error. – duffn Dec 04 '14 at 18:23
  • When attempting to add or update a record via the admin interface. – duffn Dec 04 '14 at 19:59