首页 文章

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

提问于
浏览
25

我试图覆盖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 回答

  • 2

    首先,这不是一个错误,它是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
    

    最后,为了更直接地回答您的问题,您可以通过检查 form.changed_data 来检查 save_model 方法中的字段是否已更改 . 这是已更改字段的名称列表 .

    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

    你始终可以使用 MyVehicles.objects.get(pk=obj.pk) 从数据库中找到值

  • 15

    好的,我找到了解决办法 . 这对我来说似乎仍然是个错误 .

    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.")
    
  • 46

    对于那些想知道 change 参数的人:

    如果这是对现有模型的更改,则此参数将为True;如果模型是新创建的实例,则此参数为False .

    要检查是否有任何字段已更改: form.changed_data 将包含已更改的字段,这意味着如果没有更改,则该字段为空 .

相关问题