重写子/继承表单中父django表单的clean()方法

重写子/继承表单中父django表单的clean()方法,django,Django,我真的很难弄明白这一点。最根本的问题是,我需要以某种方式为password字段设置初始值,或者覆盖方法validate_成员的调用方式 我有一个表格,当会员需要直接向系统注册时,它被称为: class NewMemberForm(forms.Form): ''' Called when user wants to register with our system from web/mobile. Ask password here ''' firstName=

我真的很难弄明白这一点。最根本的问题是,我需要以某种方式为password字段设置初始值,或者覆盖方法validate_成员的调用方式

我有一个表格,当会员需要直接向系统注册时,它被称为:

class NewMemberForm(forms.Form):
    '''
    Called when user wants to register with our system from web/mobile. Ask password here

    '''

    firstName=forms.CharField(max_length=25,required=True,widget=forms.TextInput())
    lastName=forms.CharField(max_length=25,required=True,widget=forms.TextInput())
    birthdate=forms.DateField(required=True)
    gender=forms.ChoiceField(choices=Profile.GENDER,required=True)
    idnumber=forms.CharField(required=False,max_length=25)
    phone=forms.IntegerField(required=True)
    email=forms.EmailField(required=True)
    password=forms.CharField(max_length=16,widget=forms.PasswordInput())
    memberType=forms.ChoiceField(choices=Profile.TYPE_OF_MEMBER,widget=forms.Select())
    maritalStatus=forms.ChoiceField(choices=Profile.MARITAL_STATUS,widget=forms.Select())



    def clean(self):
        '''
        Grouped cleaning
        '''
        self.cleaned_data=super(NewMemberForm,self).clean()

        validate_member_form=validate_member(self.cleaned_data,False)

        #do we have error messages now?

        if len(validate_member_form[0])>0: #yes we have error messages
            raise forms.ValidationError(_(validate_member_form[0]),code='invalid')

        return validate_member_form[1]
validate_member函数在编辑和添加信息时使用,因此清洁了clean()以保持干燥。现在,我有另一个场景,其中一个成员可以由另一个成员注册(具有一些权限)。在这种情况下,在名为role的表单中添加一个新字段时,不需要password和membertype字段;所以我决定继承表格:

class MemberAddForm(NewMemberForm):

    #memberType=forms.CharField(initial='Individual',required=False,widget=forms.Select()) #iignored: here to simple override the Required declaraton in memberform
    #password=forms.CharField(max_length=16,widget=forms.PasswordInput(),required=False,initial='111111') #note pwd is ignored during saving and a new is generated
    role=forms.ModelChoiceField(widget=forms.Select(),required=True,queryset=Activity.objects.filter(active='Active').only('id','name'),empty_label=None)

    def __init__(self,*args,**kwargs):
        super(MemberAddForm,self).__init__(*args,**kwargs)
        self.fields['password'].initial='123456' #note this is meangingless and in place to pass validate_member
        self.fields['password'].required=False
        self.fields['memberType'].initial='Individual'
        self.fields['memberType'].required=False

    def clean(self):
        '''
        This is not been used at all.
        '''

        self.cleaned_data=super(MemberAddForm,self).clean()
        self.cleaned_data['password']='!983.kIl'


        #validate_member_form=validate_member(self.cleaned_data,False,False)

        #do we have error messages now?

        if len(validate_member_form[0])>0: #yes we have error messages
            raise forms.ValidationError(_(validate_member_form[0]),code='invalid')

现在,我注意到子类中的clean()方法被完全忽略,验证只由parent.clean()处理。我真的需要在validate_成员方法中将第三个参数作为False传递(在父类中为True)。validate_成员检查密码复杂性和其他内容。设置required=False有一定帮助,因为不再显示“此字段为required”错误;但是,密码仍然处于检查状态。如您所见,我将密码设置为通过密码设置的初始值,但无论我做什么,仍然会出现错误。

子类中的这一行导致调用父类的
clean
方法:

self.cleaned_data=super(MemberAddForm,self).clean()
由于两者几乎相同,看起来孩子的一个没有被调用,也就是说,如果父母的
clean
成功通过,孩子的一个也会被调用

您的问题的解决方案是将paren的
clean
方法修改为:

   def clean(self, validate_member=True):
        '''
        Grouped cleaning
        '''
        self.cleaned_data=super(NewMemberForm,self).clean()

        if validate_member:
            validate_member_form=validate_member(self.cleaned_data, False)

        # Do we have error messages now?
        if len(validate_member_form[0]) > 0:  # yes we have error messages
            raise forms.ValidationError(_(validate_member_form[0]), code='invalid')

        return validate_member_form[1]
然后,在child的
clean
方法中,您需要做的就是:

def clean(self):
    return super(NewMemberForm,self).clean(validate_member=False)

还有另一种选择

# dynamic form creation
class CreateUpdateView(FormView):
    template_name = 'apps/frontend/create_update_view.j2'
    def get_form_class(self):
        # url like: /user/(?P<mode>[^/]+)/ - /user/register/ or /user/update/
        is_password_required = self.kwargs.get('mode') == 'register'

        class _Form(forms.Form):
            if is_password_required:
                password = forms.CharField(widget=forms.PasswordInput)

            first_name = forms.CharField(max_length=25, required=True)

        return _Form
#动态表单创建
类CreateUpdateView(FormView):
template_name='apps/frontend/create_update_view.j2'
def get_form_类(自我):
#url类似于:/user/(?P[^/]+)/-/user/register/或/user/update/
是否需要密码=self.kwargs.get('mode')='register'
班级表格(表格.表格):
如果需要密码:
password=forms.CharField(widget=forms.PasswordInput)
first_name=forms.CharField(最大长度=25,必需=True)
报税表

它确实有效,但我认为Domen的解决方案更容易合并到我当前运行的应用程序中。感谢Vadimchin提供了我根本没有想到的替代解决方案。很抱歉,我错误地将您的评论标记为答案。但我不确定clean()方法是否接受参数?或者它是完全干净的,不干净。请让我试试。可以定义额外的参数(即在父函数
clean
函数中),只需确保设置默认值,这样就可以用标准的Django方式调用它们。