6

我正在尝试在 Django 中执行此操作:在管理员中保存对象时,我还想根据我的第一个对象中的一个字段保存另一个不同类型的对象。为了做到这一点,我必须检查第二个对象是否已经存在,如果存在,则仅针对第一个对象中的特定字段返回验证错误。我的问题是我希望验证错误仅在插入操作时出现在字段中。

如何根据知道操作是更新还是插入来显示特定管理表单字段的验证错误?

PS我知道对于模型验证这是不可能的,因为验证器只接受值参数,但我认为表单验证应该是可能的。

4

4 回答 4

13

这可以通过在 Django 管理表单中编写 clean_[name_of_field] 方法来完成。可以通过测试 self.instance.pk 来检查插入或更新操作。

class EntityAdminForm(forms.ModelForm):
    def clean_field(self):
        field = self.cleaned_data['field']
        insert = self.instance.pk == None
        if insert:
            raise forms.ValidationError('Some error message!')
        else:
            pass
        return field

class EntityAdmin(admin.ModelAdmin):
    form = EntityAdminForm

在向 Django 管理员注册实体模型时,您必须使用 EntityAdmin 类:

admin.site.register(Entity, EntityAdmin)
于 2012-10-03T12:52:52.500 回答
0

您可以在模型级别编写自定义验证

#inside your class model ...
def clean(self):
    is_insert = self.pk is None
    from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
    #do your business rules
    if is_insert:
        ...
        if __some_condition__ :
            raise ValidationError('Dups.')
于 2012-10-03T11:56:48.197 回答
0

为您的模型创建模型表单。在该clean方法中,您可以为特定字段设置错误。

有关更多信息,请参阅清理和验证相互依赖的字段的文档。

于 2012-10-03T12:26:25.173 回答
0

那(可能)不是一个确切的答案,但我想它可能会有所帮助。

Django Admin 为您提供了save使用 ModelAdmin.save_model 方法覆盖方法(文档在这里

Django api 也有一个get_or_create方法(Doc is here)。它返回两个值,第一个是对象,第二个是一个布尔值,表示是否创建了对象(更新了现有记录)。

让我说你FirstObjectSecondObject

在您的相关admin.py文件中:

class FirstObjectAdmin(admin.ModelAdmin):
...
...
    def save_model(self, request, obj, form, change):
        s_obj, s_created = SecondObject.objects.get_or_create(..., defaults={...})
        if not s_created:
            #  second object already exists... We will raise validation error for our first object
            ...

对于其余部分,我对如何处理它没有明确的想法。由于您手头有表单对象,因此您可以为 admin 调用form.fields{'somefield'].validate(value)编写自定义验证。您可能会覆盖clean方法并尝试触发raise ValidationErrorfromModelAdmin.save_model方法。你可以从那里调用validate并传递一个值......

您可以挖掘 django 源代码以查看 django 是如何处理此问题的,并尝试定义一些自定义验证步骤。

于 2012-10-03T15:22:24.057 回答