2017-06-18 73 views
1

我真的很難搞清楚這一點。最基本的問題是我需要以某種方式設置密碼字段的初始值或覆蓋方法validate_member的調用方式。覆蓋子/繼承形式的父django表單的clean()方法

我有這樣的形式,其被調用時的成員需要註冊到系統直接:

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功能被使用,從而清潔的清潔()保持事情幹。現在,我有另一種情況,其中一個成員可以由另一個成員註冊(有一些權利)。在這種情況下,密碼和membertype字段不需要添加到名爲role的表單中的一個新字段;所以我決定繼承的形式:

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') 

現在,我注意到在子類的清潔()方法被完全忽略和驗證正在從parent.clean照顧()只。我真的需要在validate_member方法中將第三個參數作爲False傳遞(在Parent類中爲True)。 validate_member檢查密碼的複雜性和東西。設置required = False部分是因爲'此字段是必需的'錯誤不再顯示;然而,密碼仍然是複雜的檢查。正如你所看到的,我將密碼設置爲傳遞密碼設置的初始值,但無論我做什麼,我仍然得到錯誤。

回答

0

這條線子類是導致該父的clean方法被稱爲:

self.cleaned_data=super(MemberAddForm,self).clean() 

由於兩者幾乎相同,它看起來像孩子的一個不叫,也就是說,如果父母的clean成功也通過孩子會的。

解決您的問題將是修改括號的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] 

然後你有孩子的clean方法做的是:

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

對不起,我錯誤地將您的評論標記爲答案。但我不確定clean()方法是否接受爭論?或者它完全乾淨,沒有。請讓我試試。 –

+0

可以定義額外的參數(即在父類'clean'函數中),只要確保設置默認值,這樣就可以用標準的Django方式調用它們。 –

1

還有另一種選擇

# 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 
+0

它確實有效,但我認爲Domen的解決方案更容易合併到我當前運行的應用程序中。感謝Vadimchin提供了我根本沒有想到的替代解決方案。 –

+0

不客氣) – vadimchin