У меня есть модель, которая требует некоторой постобработки (я генерирую MD5 из поля body).

models.py

class MyModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    body = models.TextField()
    md5 = models.CharField(max_length=32)
    ...

    def save(self, *args, **kwargs):
        if self.pk is None: # Only for create (edit disabled)
            self.md5 = get_md5(self.body)
            super(MyModel, self).save(*args, **kwargs)

Проблема в том, что последний блок не будет выполнен, потому что я не вижу способа проверить, является ли экземпляр новым или нет: self.pk никогда не None, потому что UUID заполняется перед сохранением.

Я хотел бы знать, как лучше всего справляться с этим.

Заранее спасибо.

Обновление:

Единственное решение, которое я могу придумать, - это вызвать базу данных напрямую и:

  1. Проверьте, существует ли id
  2. Сравните поля modified и created, чтобы определить, является ли это редактированием.
5
Daniel van Flymen 15 Дек 2015 в 10:21

4 ответа

Лучший ответ

Похоже, что самый чистый подход к этому - убедиться, что у всех ваших моделей есть created дата на них, наследуя от Абстрактной модели, тогда вы просто проверяете, имеет ли created значение:

models.py

class BaseModel(models.Model):
    """
    Base model which all other models can inherit from.
    """
    id = fields.CustomUUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        # Abstract models are not created in the DB
        abstract = True

class MyModel(BaseModel):
    my_field = models.CharField(max_length=50)

    def save(self, *args, **kwargs):
        if self.created:
            # Do stuff
            pass
        super(MyModel, self).save(*args, **kwargs)
1
Daniel van Flymen 25 Янв 2016 в 22:14

Я только что получил ту же проблему в своем проекте и обнаружил, что вы можете проверить внутреннее состояние экземпляра модели:

def save(self, *args, **kwargs):
    if self._state.adding: # Only for create (edit disabled)
        self.md5 = get_md5(self.body)
        super(MyModel, self).save(*args, **kwargs)

Но это решение основано на внутренней реализации и может перестать работать после обновления Django.

2
Sergey Shishov 6 Авг 2018 в 13:26

РЕДАКТИРОВАТЬ

self.pk никогда не является None, потому что UUID заполняется перед сохранением.

Вместо установки значения по умолчанию для id используйте метод для установки id для нового экземпляра.

class MyModel(...):
    id = models.UUIDField(primary_key=True, default=None,...)

    def set_pk(self):
        self.pk = uuid.uuid4()

    def save(self, *args, **kwargs):
        if self.pk is None:
            self.set_pk()
            self.md5 = get_md5(self.body)
            super(MyModel, self).save(*args, **kwargs)
3
xyres 15 Дек 2015 в 07:48