Условное сохранение () при обновлении? - PullRequest
0 голосов
/ 29 января 2020

У меня небольшая прямая проблема. Тем не менее, мне трудно ее решить.

У меня есть одна упрощенная модель:

class Post(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) 
    author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    creation_date_time = models.DateTimeField(auto_now_add=True)
    is_published = models.BooleanField(default=False)
    title = models.CharField(max_length=255, blank=True, null=True)        

    def save(self, *args, **kwargs):
        if not self.creation_date_time:
            existing_post = \
                self.author.post_set \
                .filter(
                    is_published=False, 
                    conversation=self.conversation) \
                        .exists()
            if existing_post:
                raise IndexError
    super().save(*args, **kwargs)

Теперь я хочу проверить, что: У каждого автора может быть только один неопубликованная (черновик) публикация.

Текущий код проверяет это при создании экземпляра, но становится довольно сложным, когда экземпляр обновляется и не создается, например, через django admin.

Важно, однако, что можно обновлять свойства модели независимо от is_published. Только создание двух или более сообщений с is_published=True на пользователя должно вызвать ошибку.

Есть ли способ сделать это, чего я не вижу?

РЕДАКТИРОВАТЬ: Благодаря @ nigel222 я смог решить свою проблему. Вот моя реализация:

def save(self, *args, **kwargs):
    if self.is_published == False:
        existing_post_uuids = \
            self.author.post_set \
                .filter(
                    is_published=False,
                    conversation=self.conversation) \
                        .values_list('uuid', flat=True)
        if len(existing_post_uuids) == 0 \
            or existing_post_uuids[0] == self.uuid:
            super().save(*args, **kwargs)
        else:
            raise ValidationError('Users can only have one draft per conversation')
    super().save(*args, **kwargs)

Ответы [ 4 ]

1 голос
/ 29 января 2020

При обновлении будет сохранен объект с self.pk. Новый объект будет self.pk is None. Проверьте это в своем сохранении:

def save(self, *args, **kwargs):
    if self.pk is not None:
        return super().save( *args, **kwargs) # was an update

    # if still here we are saving a newly created object
    ...
0 голосов
/ 29 января 2020

Ваш тест в настоящее время не исследует, относится ли exists() к нам или нет. Как насчет

        existing_post_uuids = \
            self.author.post_set \
            .filter(
                is_published=False, 
                conversation=self.conversation) \
            .values_list( 'uuid', flat=True)
        if len( existing_post_uuids) > 1:
             # this shouldn't be possible ...
        elif len(existing_post_uuids) == 0:
             # creating - OK - none presently exists
        elif existing_post_uuids[0] == self.uuid:
             # updating
        else:
             # trying to create a second one
0 голосов
/ 29 января 2020

Чтобы проверить, выполняется ли сохранение или обновление:

def save(self, *args, **kwargs):
   is_new = self._state.adding
   if is_new:
       pass # adding new object.
   else:
       pass # updating the existing object.
   super().save( *args, **kwargs)
0 голосов
/ 29 января 2020

Возможным решением здесь является переопределение AdminModel save_model метода. Затем вы можете проверить, есть ли у автора черновик сообщения, и поднять Проверка Ошибка.

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