【问题标题】:Changing a form field's 'required' property with save_model in Django admin在 Django admin 中使用 save_model 更改表单字段的“必需”属性
【发布时间】:2019-04-23 13:55:05
【问题描述】:

为此,我已经尝试了在 Stack Overflow 上可以找到的所有不同示例和方法,但无论出于何种原因,都无法使其正常工作。

所以在我的 admin.py 中,我有一个 UserForm 和一个 UserAdmin。根据在表单中检查布尔值的条件,我想将几​​个不同表单字段上的“必需”属性更改为“假”,这样我就可以有效地保存。我已经使用了一些不同的打印语句来确定“必需”实际上在满足条件时被更改为 false,但是,当我尝试保存时,它不会让我因为字段突出显示并说他们'仍然是必需的。

几乎就像 save_model 不关心我如何编辑表单一样,旧表单及其“必需”属性覆盖了我的更改。感谢您的帮助!

admin.py

class UserForm(forms.ModelForm):
    state = forms.CharField(min_length=2, widget=forms.TextInput(attrs={'placeholder':'CA'}))
    zipcode = forms.CharField(max_length=5, min_length=5,)

    class Meta:
        model = User
        fields = '__all__'


class UserAdmin(admin.ModelAdmin):
    model = Order
    form = UserForm

    def save_model(self, request, obj, form, change):
        if obj.pickup_only == 1:
            form.fields['address'].required = False
            form.fields['city'].required = False
            form.fields['state'].required = False
            form.fields['zipcode'].required = False
        return super(UserAdmin, self).save_model(request, obj, form, change)

修改后的用户窗体代码:

def clean(self):
    cleaned_data = super(UserForm, self).clean()
    address = cleaned_data.get('address')
    state = cleaned_data.get('state')
    city = cleaned_data.get('city')
    zipcode = cleaned_data.get('zipcode')
    pickup_only = cleaned_data.get('pickup_only')

    if pickup_only == True:
        # I STUCK IN ADDRESS TO EMPHASIZE THE ERROR IN SCREENSHOT
        self.fields_required(['first_name', 'last_name', 'dob', 'phone', 'email', 'address'])
    else:
        self.cleaned_data['address', 'city', 'state', 'zip code'] = ''
    return self.cleaned_data

def fields_required(self, fields):
    for field in fields:
        print(field)
        # RETURNS: first_name, last_name, dob, phone, email, address
        if not self.cleaned_data.get(field, ''):
            msg = forms.ValidationError("This field is required. Custom.")
            self.add_error(field, msg)

当我保存时,我得到了这个:

【问题讨论】:

  • 可以加UserForm吗?
  • 是的,先生,会的..
  • 除此之外,在您的 UserAdmin 类中您定义了 model = Order 并在您的 UserForm 中定义了 model = User。这会是个问题吗?
  • 我的 UserAdmin 中有 model = order,因为它引用了用于内联显示的模型类。由于这不是在 save_model 函数中传递的参数,因此我认为它不相关。无论如何,我将其注释掉,看看是否会对代码不起作用有任何影响,但不幸的是没有。
  • 我认为更好的是,将模型中的这些字段定义为blank=True 并在clean() 表单方法中手动处理验证

标签: django django-models django-forms django-rest-framework django-admin


【解决方案1】:

您可能需要稍微调整一下以满足您的需求,但您可以在您的 clean 方法中尝试这样的事情:

def clean(self):
    cleaned_data = super(UserForm, self).clean()
    state = cleaned_data.get('state')
    zipcode = cleaned_data.get('zipcode')
    pickup_only = cleaned_data.get('pickup_only')

    if pickup_only == True:
        self.fields_required(['any_fields_required',])
    else:
        self.cleaned_data['state', 'zip code'] = ''
    return self.cleaned_data

def fields_required(self, fields):
    for field in fields:
        if not self.cleaned_data.get(field, ''):
            msg = forms.ValidationError("This field is required.")
            self.add_error(field, msg)

此外,正如其中一位评论者所提到的,您不应在 UserAdmin 中指定您的 model=Order。您的 UserAdmin 用于 User 模型。这不是添加内联的正确方法。见下文:

# You can also use (admin.TabularInline) depending on your needs.
class OrderInline(admin.StackedInline):
    model = Order
    list_display = ('order_fields',)
    fieldsets = (
        ((''), {'fields': ('order_fields',)}),
    )

class UserAdmin(admin.ModelAdmin):
    model = User
    inlines = [OrderInline,]

在表单中添加一个 init 方法:

class UserForm(forms.ModelForm):
    state = forms.CharField(min_length=2, widget=forms.TextInput(attrs={'placeholder':'CA'}))
    zipcode = forms.CharField(max_length=5, min_length=5,)

    class Meta:
        model = User
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)
        self.fields['address'].required = False
        self.fields['city'].required = False
        self.fields['state'].required = False
        self.fields['zipcode'].required = False

    def clean(self):
        cleaned_data = super(UserForm, self).clean()
        address = cleaned_data.get('address')
        state = cleaned_data.get('state')
        city = cleaned_data.get('city')
        zipcode = cleaned_data.get('zipcode')
        pickup_only = cleaned_data.get('pickup_only')

        if pickup_only == True:
            self.fields_required(['first_name', 'last_name', 'dob', 'phone', 'email', 'address'])
        else:
            self.cleaned_data['address', 'city', 'state', 'zip code'] = ''
        return self.cleaned_data

    def fields_required(self, fields):
        for field in fields:
            if not self.cleaned_data.get(field, ''):
                msg = forms.ValidationError("This field is required. Custom.")
                self.add_error(field, msg)

试试这个。如果它有效,那么我认为您不必覆盖 UserAdmin 中的保存方法。除非绝对必要,否则我会避免这种情况。

【讨论】:

  • 感谢您的回复!我尝试了上面的代码来适应我需要的字段,但它似乎不起作用。似乎没有正确调用 fields_required 方法。我尝试从调试方法中打印,但尝试保存时无法获得任何输出。我做错了吗?
  • @Dev - 如果有错误,您会遇到什么错误?表格中发生了什么?模型保存了吗?
  • 我没有返回任何错误,但是,我一直在弄乱代码以更好地了解发生了什么。到目前为止,我有:如果pickup_only 为真, self.fields_required(['first_name', 'last_name', 'dob', 'phone', 'email',]) --> 这些是我想要的字段。然后对于 ELSE,我有地址字段(城市、州、邮编)。对于 fields_required 方法,当我打印字段时,它会打印除地址字段之外的所有内容。我尝试将“地址”添加到 self.fields_required 数组并吐出错误消息,但我显然做错了什么或把事情搞混了。
  • @Dev - 仅在pickup_only时尝试:
  • @Dev - 啊我想我知道问题所在。这是我的错误。再次查看答案以了解更改。将 fields_required 方法移到 clean 方法之外。
猜你喜欢
  • 2020-04-15
  • 2013-08-02
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
  • 2012-02-25
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多