Подтвердить что ты не робот

Django Admin - метод save_model - как определить, изменилось ли поле?

Я пытаюсь переопределить метод save_model в объекте admin Django, чтобы пользователь не мог изменять определенное поле. Однако я не могу найти способ узнать, изменилось ли поле в этом методе.

Здесь мой код:

def save_model(self, request, obj, form, change):
    if change: 
        if obj.parking_location == form.cleaned_data['parking_location']:
            super(MyVehiclesAdmin, self).save_model(request, obj, form, change)
        else:
            messages.error(request, 
                "The Parking Location field cannot be changed.")

Проблема заключается как в obj.parking_location, так и в form.cleaned_data ['parking_location'] имеют новое значение. (Может ли это быть ошибкой в ​​Django? Кажется, что obj должен содержать значения pre-save). В любом случае, есть ли другой способ сделать это?

(Я на Django 1.2)

4b9b3361

Ответ 1

Во-первых, это не ошибка, это документированное поведение в Django 1.2 и далее.

Из примечания к выпуску Django 1.2:

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

Если вы хотите, чтобы пользователь не редактировал поле paticular, лучшим вариантом может быть использование опции ModelAdmin.readonly_fields.

class VehicleRegistrationAdmin(admin.ModelAdmin):
    readonly_fields = ('parking_location',)

Или вы можете заменить ModelAdmin.form на пользовательскую форму, которая исключает это поле.

class VehicleRegistrationForm(forms.ModelForm):
    class Meta:
        exclude = ('parking_location',)

class VehicleRegistrationAdmin(admin.ModelAdmin):
    form = VehicleRegistrationForm

Наконец, чтобы более точно ответить на ваш вопрос, вы можете проверить, изменилось ли поле в методе save_model, проверив form.changed_data. Это список имен полей, которые изменились.

def save_model(self, request, obj, form, change):
    if 'parking_location' in form.changed_data:
        messages.info(request, "Parking location has changed")
    else:
        messages.info(request, "Parking location has not changed")
    super(MyVehiclesAdmin, self).save_model(request, obj, form, change)

Ответ 2

Для тех, кто задается вопросом о параметре change:

Этот параметр будет True, если это изменение в существующей модели, это False, если модель является вновь созданным экземпляром.

Чтобы проверить, были ли изменены какие-либо поля: form.changed_data будет содержать измененные поля, что означает, что он пуст, если изменений нет.

Ответ 3

вы всегда можете найти значение из db с помощью MyVehicles.objects.get(pk=obj.pk)

Ответ 4

Хорошо, я нашел работу. Это все еще кажется ошибкой для меня.

def save_model(self, request, obj, form, change):
    if change: 
        vr = VehicleRegistration.objects.get(pk=obj.id)
        if vr.parking_location == form.cleaned_data['parking_location']:
            super(MyVehiclesAdmin, self).save_model(request, obj, form, change)
        else:
            messages.error(request, 
                "The Parking Location field cannot be changed.")