Как проверить переход значения в Django (django-admin)? - PullRequest
8 голосов
/ 15 мая 2009

У меня есть поле состояния, которое имеет 3 значения: в ожидании, активирован и отклонил. Если я изменяю значение статуса, я хочу проверить, что активированный не может быть изменен на ожидающий. я не хочу писать хранимые процедуры для этого. Могу ли я иметь предыдущее значение в Django перед сохранением?

Означает новое и старое значение.

Ответы [ 5 ]

10 голосов
/ 15 мая 2009
def clean_status(self):
    status = self.cleaned_data.get('status')
    if status == 'pending':
        if self.instance and self.instance.status == 'activated':
            raise forms.ValidationError('You cannot change activated to pending')

    return status

Этот метод должен быть добавлен в подкласс Form. Его зовут clean_FIELD_NAME.

cleaned_data содержит предыдущие значения. Новое значение сохраняется в self.instance.

Кроме того, метод validate() может быть добавлен к подклассу forms.Field См. Документацию Django.

9 голосов
/ 15 мая 2009

Вы можете сделать это переопределенным методом save. Следует помнить, что экземпляры модели Django не являются реальными объектами базы данных, они просто получают свои значения оттуда при загрузке. Таким образом, вы можете легко вернуться к базе данных перед сохранением текущего объекта, чтобы получить существующие значения.

def save(self, *args, **kwargs):
    if self.status == 'pending':
         old_instance = MyClass.objects.get(pk=self.pk)
         if old_instance.status == 'activated':
              raise SomeError
     super(MyModel, self).save(*args, **kwargs)

В настоящее время нет другого способа вернуть пользователю сообщение об ошибке, кроме как вызвать исключение. В настоящее время реализуется проект Google Summer of Code, позволяющий включить проверку модели, но он не будет готов в течение нескольких месяцев.

Если вы хотите сделать что-то подобное в админке, лучше всего определить пользовательскую ModelForm с переопределенным методом clean(). Однако на этот раз, так как это форма, у вас уже есть доступ к старым значениям без повторного нажатия на базу данных. Еще одним преимуществом является то, что вы можете вернуть пользователю ошибку проверки формы.

class MyModelForm(forms.ModelForm):

     class Meta:
          model = MyModel

    def clean_status(self):
        status = self.cleaned_data.get('status', '')
        if status == 'pending':
             if self.instance and self.instance.status == 'activated':
                  raise forms.ValidationError(
                      'You cannot change activated to pending'
                  )
         return status

 class MyModelAdmin(forms.ModelAdmin):
     form = MyModelForm
     model = MyModel
1 голос
/ 10 ноября 2011

В другом месте об переполнении стека ответили, но правильный способ - использовать что-то вроде this , чтобы отслеживать, не загрязнены ли поля. Тогда вы можете использовать сигнал, чтобы указать, что что-то изменилось, что важно. (т. е. ваше поле)

0 голосов
/ 20 февраля 2012

Нашел эту ветку при поиске ответа на тот же вопрос. Почему бы не сделать что-то подобное? Таким образом, вы можете избежать прикосновения к базе данных. И встроенный __init__ просто немного расширен. Я думаю, что это гораздо более простой способ, чем использование сигналов.

class MyModel(models.Model):
    my_fair_field = ....

    def __init__(self, *args, **kwargs):
        super(MyModel, self).__init__(*args, **kwargs)
        self.__clean_fair_field = self.my_fair_field

    def save(self, *args, **kwargs):
        # check if field value changed
        if self.__clean_fair_field != self.my_fair_field
                 # ...do some work...

        super(MyModel, self).save(*args, **kwargs)
0 голосов
/ 15 мая 2009

Вместо того, чтобы переопределять метод сохранения, разве это не было бы хорошим местом для использования сигналов? Перехватить сохранение перед фиксацией, проверить текущее значение в базе данных и либо переслать сохранение, либо отклонить его?

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

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

...