在Django

时间:2015-05-11 17:19:40

标签: django django-forms

我有一个UserProfile模型,它将OneToOne与Django User模型相关联。在通过表单添加用户时,我希望为这两个表单添加一个表单。我发现了一个完全相同的代码片段,我没有遇到任何问题,直到我想验证username。该表单不会像我希望的那样抛出ValidationError,但会返回包含ValueError: The User could not be created because the data didn't validate.的错误页面。

根据我的理解(显然可能是错误的),当前设置不会从嵌套表单处理ValidationError

有没有办法添加该功能?如果没有,我应该如何处理模型的一个表格处理问题?

代码:

class CmUserForm(forms.ModelForm):
   password = forms.CharField(widget=forms.PasswordInput(),
                              required=False,
                              help_text=_("Leave empty if you don't want "
                                          "to change it"))

   def clean_password(self):
       data = self.cleaned_data['password']
       if data.strip():
           return make_password(data)
       else:
           # If password field is empty, then don't change it
           return self.instance.password

    def clean_username(self):
       username = self.cleaned_data['username']

       if get_user_model().objects.filter(username=username).exists():
           raise forms.ValidationError(_('This username is already in use.'))
       return username

    class Meta:
        model = get_user_model()
        fields = ('first_name', 'last_name', 'email', 'username', 'password', 'is_staff', 'is_active')


class CmUserProfileForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        # Take User if updating, None if creating
        try:
            self.user = kwargs['instance'].user
        except AttributeError:
            self.user = None

        user_kwargs = kwargs.copy()
        user_kwargs['instance'] = self.user
        self.uf = CmUserForm(*args, **user_kwargs)

        super(CmUserProfileForm, self).__init__(*args, **kwargs)

        self.fields.update(self.uf.fields)
        self.initial.update(self.uf.initial)

    class Meta:
        model = UserProfile
        exclude = ['user']

    def save(self, *args, **kwargs):
        # Save User and pass it to UserProfile
        user = self.uf.save(*args, **kwargs)
        self.instance.user = user
        return super().save(*args, **kwargs)

1 个答案:

答案 0 :(得分:1)

我今天也实现了同样的目标。我从django的这个网站探戈中学到了这一点。 http://www.tangowithdjango.com/book/chapters/login.html。我也提供了我的代码,我是如何实现这一目标内置用户模型本身会检查用户名是否已存在。希望这很有帮助。

class Sam(models.Model):
      user = model.OneToOneField(User)
      #custom fields apart from the inbuilt User model
      region = models.CharField(max_length=10)
      designation = models.CharField(max_length=10)
#forms.py form models. Created SamProfileform  to capture the custom fields which are specific to One's Profile and SamForm to capture the password and then hash later in the view. 
#Please note that i didnt add any username check here. The inbuilt User does it for us. I verified it.
class SamForm(forms.ModelForm):
      #form model to capture inbuilt fields of "User" model
      password = forms.CharField(widget=PasswordInput())
      class Meta:
            model = User
            fields = ('username', 'email', 'password', 'firstname', 'lastname')
class SamProfileForm(forms.ModelForm):
       #form model to built the custom fields in my case region and designation
       class Meta:
             model = Sam
             fields = ('desgination', 'mgr')
def register(request):
    registered = False
    if request.method == 'POST':
         user_form = SamForm(data=request.POST)
         profile_form = SamProfileForm(request.POST)
         if user_form.is_valid() and profile_form.is_valid():
            user = user_form.save()
            user.set_password(user.password)
            user.save()
            profile = profile_form.save(commit=False)
            profile.user = user
            profile.save()
            registered = True
         else:
            print user_form.errors, profile_form.errors
   else:
       user_form = SamForm()
       profile_form = SamProfileForm()
   template = loader.get_template('sam/register.html')
   context = RequestContext(request, {
            'user_form' : user_form, 'profile_form' : profile_form, 'registered' : registered,
    })
   return HttpResponse(template.render(context))