我正在尝试覆盖save_model method on a Django admin object以阻止用户更改某个字段。但是我无法找到方法来确定该方法中的字段是否已更改。
到目前为止,这是我的代码:
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应该包含预保存值)。无论如何,还有另一种方法可以实现这一目标吗?
(我在Django 1.2上)
答案 0 :(得分:51)
首先,这不是一个错误,它是Django 1.2以后记录的行为。
首次致电
ModelForm.is_valid()
,访问ModelForm.errors
或以其他方式触发表单验证时,您的模型将就地清理。这种转换过去是在保存模型时发生的。如果需要未修改的模型实例,则应将副本传递给ModelForm构造函数。
如果您想阻止用户编辑特定字段,更好的方法可能是使用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)
答案 1 :(得分:18)
对于那些想知道change
参数的人:
如果这是对现有模型的更改,则此参数为True;如果模型是新创建的实例,则此参数为False。
要检查是否有任何字段已更改:form.changed_data
将包含已更改的字段,这意味着如果没有更改,则字段为空。
答案 2 :(得分:2)
您始终可以使用MyVehicles.objects.get(pk=obj.pk)
答案 3 :(得分:1)
好的,我找到了解决办法。这对我来说似乎仍然是个错误。
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.")