Django Admin - save_model方法 - 如何检测字段是否已更改?

时间:2011-11-08 19:45:33

标签: django django-admin

我正在尝试覆盖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上)

4 个答案:

答案 0 :(得分:51)

首先,这不是一个错误,它是Django 1.2以后记录的行为。

来自Django 1.2 release notes

  

首次致电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.")