actions - Django Admin-método save_model-¿Cómo detectar si un campo ha cambiado?
django admin actions (4)
En primer lugar, esto no es un error, es el comportamiento documentado en Django 1.2 en adelante.
De las notas de lanzamiento de Django 1.2 :
la primera vez que llame a
ModelForm.is_valid()
, acceda aModelForm.errors
o active la validación de formularios, su modelo se limpiará en el lugar. Esta conversión solía ocurrir cuando se guardaba el modelo. Si necesita una instancia no modificada de su modelo, debe pasar una copia al constructor de ModelForm.
Si desea evitar que el usuario edite un campo específico, un mejor enfoque podría ser utilizar la opción ModelAdmin.readonly_fields
.
class VehicleRegistrationAdmin(admin.ModelAdmin):
readonly_fields = (''parking_location'',)
O bien, podría reemplazar el ModelAdmin.form
con un formulario personalizado que excluya ese campo.
class VehicleRegistrationForm(forms.ModelForm):
class Meta:
exclude = (''parking_location'',)
class VehicleRegistrationAdmin(admin.ModelAdmin):
form = VehicleRegistrationForm
Finalmente, para responder a su pregunta de manera más directa, puede verificar si un campo ha cambiado en el método form.changed_data
inspeccionando form.changed_data
. Esta es una lista de los nombres de los campos que han cambiado.
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)
Estoy intentando anular el método save_model en un objeto de administración de Django para evitar que un usuario cambie un campo determinado. Sin embargo, no puedo encontrar una manera de averiguar si el campo ha cambiado dentro de este método.
Aquí está mi código hasta ahora:
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.")
El problema es que tanto obj.parking_location como form.cleaned_data [''parking_location''] tienen el nuevo valor. (¿Podría ser esto un error en Django? Realmente parece que el objeto debe contener los valores de pre-guardado). En cualquier caso, ¿hay otra manera de lograr esto?
(Estoy en Django 1.2)
Ok, encontré una solución alternativa. Aunque esto todavía me parece un error.
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.")
Para aquellos que se preguntan sobre el parámetro de change
:
Este parámetro será verdadero si se trata de un cambio en un modelo existente, es falso si el modelo es una instancia recién creada.
Para verificar si se ha cambiado algún campo: form.changed_data
contendrá los campos modificados, lo que significa que está vacío si no hay cambios.
siempre puede encontrar el valor de la base de MyVehicles.objects.get(pk=obj.pk)
con MyVehicles.objects.get(pk=obj.pk)