Метод save () модели Django не вызывается при использовании Model.objects.create () - PullRequest
0 голосов
/ 27 марта 2019

У меня есть первичный ключ ID CharField в моей модели Image, я хочу создать уникальные идентификаторы для вновь создаваемых объектов.Я пытаюсь достичь этого путем переопределения метода сохранения модели:

    def save(self, *args, **kwargs):
        if not self.pk: # is created
            self.id = uuid.uuid4().hex
            while Image.objects.filter(id=self.id).exists():
                self.id = uuid.uuid4().hex
        return super().save(*args,**kwargs)

Проблема в том, что save() не вызывается при создании объектов с Image.objects.create(), он вызывается только когда ясоздайте объект с помощью image=Image(...) и затем вызовите image.save().В результате у вновь созданного объекта нет назначенного идентификатора, если он не указан, что заставляет PostgreSQL выдавать ошибку non_unique primary key.

Как я могу убедиться, что уникальные идентификаторы создаются при вызове Image.objects.create()?

Версия Django: 1.11.3

ОБНОВЛЕНИЕ: Я понял, что переопределенный метод save () тоже не вызывался.Оказывается, проблема была в том, что я вызывал метод save модели в процессе миграции.Как указано в , этот пост методы пользовательской модели недоступны при переносе.Мне придется скопировать метод сохранения модели в файл миграции.

Ответы [ 2 ]

2 голосов
/ 27 марта 2019

Это не может быть сделано в целом. Между оператором if, проверяющим, что идентификатор еще не существует, и настройкой, что-то еще может добавить новую строку с этим идентификатором. Вот почему используются другие решения - автоматически увеличивающийся идентификатор, который гарантирует база данных, является уникальным, или UUID, который имеет очень малую вероятность быть уникальным.

К счастью, вы используете один из них. С UUIDs пользователь просто должен предполагать , что они уникальны.

Способ сделать это - установить функцию, возвращающую уникальный идентификатор в качестве поля по умолчанию:

def uuid_hex():
    return uuid.uuid4().hex

class YourModel(models.Model):
    id = CharField(unique=True, primary_key=True, default=uuid_hex, null=False)
0 голосов
/ 27 марта 2019

Вы должны вызвать реальный метод save при переопределении модели save метод:

def save(self, *args, **kwargs):
    if not self.pk: # is created
        self.id = uuid.uuid4().hex
        while Image.objects.filter(id=self.id).exists():
            self.id = uuid.uuid4().hex
    super(Image, self).save(*args, **kwargs)

Проверьте документы: Переопределение предопределенных методов модели

Также не рекомендуется переопределять значение по умолчанию id. Если вам нужно другое уникальное поле для использования в качестве идентификатора, тогда я рекомендую добавить другое поле рядом с полем id по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...