我试图覆盖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.leaned_data[‘parking_location’]都有新值.(这可能是Django的一个错误吗?看起来Obj确实应该包含保存前的值).无论如何,有没有其他方法可以做到这一点呢?

(我在Django 1.2上)

推荐答案

首先,这不是一个bug,而是Django 1.2以后版本中记录的行为.

Django 1.2 release notes人中:

当您第一次呼叫ModelForm.is_valid()、Access 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)

Django相关问答推荐

ModuleNotFoundError:没有名为guardian.shortcuts的模块

身份验证有效,但登录无效.一直卡在pending

Django ORM:子查询上的文本聚合器

Pytest-django - 测试创建和传递所需的用户对象

NoneType对象没有属性保存Django

使用 args 和选项编写自定义管理命令 - 所需字段说明

django-rest-framework 如何使模型序列化器字段成为必需

Django Calendar日历小部件?

Django error:不能分配必须是实例

Django - 在模板中显示当前日期和时间

Django 删除未使用的媒体文件

有 Django List View 模型排序吗?

如何覆盖 django 管理员翻译?

如何以编程方式对 Django 中的用户进行身份验证?

如何查询名称包含python列表中任何单词的模型?

将 jQuery 脚本添加到 Django 管理界面

过滤 Django 数据库中包含数组中任何值的字段

如何在该元素中的所有应用程序之间共享元素范围的模板标签

如何在 django 2.0 admin 中使用 allow_tags?

确保只有一个工作人员在运行多个工作人员的 pyramid 网络应用程序中启动 apscheduler 事件