在Django admin中使用save_model更改表单字段的'required'属性

时间:2018-11-21 02:39:52

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

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

所以在admin.py中,我有一个UserForm和UserAdmin。根据在表单中检查布尔值的条件,我想将一些不同表单字段上的“ required”属性更改为“ false”,以便可以有效保存。我使用了一些不同的打印语句来确定满足条件时,“必需”实际上已变为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)

UserForm的修订代码:

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)

保存时,我得到了:

enter image description here

1 个答案:

答案 0 :(得分:1)

您可能需要对其进行一些调整以满足您的需求,但是您可以在干净的方法中尝试如下操作:

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适用于用户模型。那不是添加内联的正确方法。见下文:

# 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,]

向表单添加一个初始化方法:

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中覆盖save方法。除非绝对必要,否则我还是会避免这种情况。