Запрет Django от обновления столбца идентичности в MSSQL - PullRequest
4 голосов
/ 23 августа 2011

Я работаю с устаревшей БД в MSSQL. У нас есть таблица с двумя столбцами, которые вызывают у меня проблемы:

class Emp(models.Model):  
    empid = models.IntegerField(_("Unique ID"), unique=True, db_column=u'EMPID')  
    ssn = models.CharField(_("Social security number"), max_length=10, primary_key=True, db_column=u'SSN') # Field name made lowercase.  

Таким образом, таблица имеет столбец ssn в качестве первичного ключа, и соответствующая часть кода обновления SQL, сгенерированного django, выглядит так:

UPDATE [EMP] SET [EMPID] = 399, 
......... 
WHERE [EMP].[SSN] = 2509882579 

Проблема в том, что EMP.EMPID является полем идентификации в MSSQL, и поэтому pyodbc выдает эту ошибку всякий раз, когда я пытаюсь сохранить изменения в существующем сотруднике:

ProgrammingError: ('42000', "[42000] [Microsoft][SQL Native Client][SQL Server]C
annot update identity column 'EMPID'. (8102) (SQLExecDirectW); [42000] [Microsof
t][SQL Native Client][SQL Server]Statement(s) could not be prepared. (8180)")

Наличие EMP.EMPID в качестве идентификатора не имеет решающего значения для любой программы, поэтому удаление его путем создания временного столбца и копирования, удаления, переименования кажется логичной вещью. Это создает еще один шаг при переносе старых клиентов в Django, поэтому мой вопрос заключается в том, есть ли способ запретить Django генерировать фрагмент «[EMPID] = XXX» всякий раз, когда я обновляю эту таблицу? *

EDIT
Я исправил свою модель так:

def save(self, *args, **kwargs):
    if self.empid:
        self._meta.local_fields = [f for f in self._meta.local_fields if f.name != 'empid']
        super().save(*args, **kwargs)

Это работает, используя преимущества того, как Django заполняет свое sql-предложение в django / db / models / base.py (525). Если у кого-то есть способ лучше или он может объяснить, почему это плохая практика, я буду рад это услышать!

1 Ответ

3 голосов
/ 06 января 2014

Этот вопрос устарел, и Синдри нашел работоспособное решение, но я хотел предложить решение, которое я использовал в производстве в течение нескольких лет, и не требующее обхода в _meta.

* 1003.* Мне пришлось написать веб-приложение, интегрированное с существующей бизнес-базой данных, содержащей много вычисляемых полей.Эти поля, обычно вычисляющие статус записи, используются практически с каждым доступом к объекту во всем приложении, и Django должен был иметь возможность работать с ними.

Эти типы полей работоспособны с менеджером моделей, которыйдобавляет в запрос обязательные поля с extra(select=...).

ComputedFieldsManager фрагментом кода: https://gist.github.com/manfre/8284698

class Emp(models.Model):
    ssn = models.CharField(_("Social security number"), max_length=10, primary_key=True, db_column=u'SSN') # Field name made lowercase.

    objects = ComputedFieldsManager(computed_fields=['empid'])


# the empid is added on to the model instance
Emp.objects.all()[0].empid

# you can also search on the computed field
Emp.objects.all().computed_field_in('empid', [1234])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...