【问题标题】:How to create a UserProfile form in Django with first_name, last_name modifications?如何在 Django 中使用 first_name、last_name 修改创建 UserProfile 表单?
【发布时间】:2010-12-16 04:49:44
【问题描述】:

如果认为我的问题很明显,几乎每个使用 UserProfile 的开发人员都应该能够回答。

但是,我在 django 文档或 Django Book 中找不到任何帮助。

当您想在 Django Forms 中创建 UserProfile 表单时,您希望修改配置文件字段以及一些 User 字段。

但是没有forms.UserProfileForm(还没有?)!

你是怎么做到的?

【问题讨论】:

    标签: python django profile django-forms


    【解决方案1】:

    这是我很久以前在我的一个项目中使用的东西,希望它可以帮助其他人在谷歌上搜索这个问题。

    class SignUpForm(forms.ModelForm):
        first_name = forms.CharField(max_length = 30)
        last_name = forms.CharField(max_length = 30)
        username = forms.CharField(max_length = 30)
        password = forms.CharField(widget = forms.PasswordInput)
        password1 = forms.CharField(widget = forms.PasswordInput)
        class Meta:
            model = UserProfile
            exclude = ['user']
    
        def clean_username(self): # check if username does not exist before
            try:
                User.objects.get(username=self.cleaned_data['username']) #get user from user model
            except User.DoesNotExist :
                return self.cleaned_data['username']
    
            raise forms.ValidationError("This user exist already choose an0ther username")
    
    
    
        def clean(self, *args , **kwargs):
            super(SignUpForm).clean(*args ,**kwargs) # check if password 1 and password2 match each other
            if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:#check if both pass first validation
                if self.cleaned_data['password1'] != self.cleaned_data['password2']: # check if they match each other
                    raise forms.ValidationError("Passwords don't match each other")
    
            return self.cleaned_data
        def save(self): # create new user
            new_user = User.objects.create_user(username=self.cleaned_data['username'],password=self.cleaned_data['password1'],email=self.cleaned_data['email'])
            new_user.first_name = self.cleaned_data['first_name']
            new_user.last_name = self.cleaned_data['last_name']
            new_user.save()
            UserProf =  super(SignUpForm,self).save(commit = False)
            UserProf.user = new_user
            UserProf.save()
            return UserProf
    

    【讨论】:

      【解决方案2】:

      您也可以尝试使用具有配置文件应用程序的 django-basic-apps 项目:

      https://github.com/nathanborror/django-basic-apps

      【讨论】:

      • 这是无用的,因为您没有从 UserProfile 和 django 用户模型创建组合表单集/
      【解决方案3】:

      这是我最后的做法:

      class UserProfileForm(forms.ModelForm):
          first_name = forms.CharField(label=_(u'Prénom'), max_length=30)
          last_name = forms.CharField(label=_(u'Nom'), max_length=30)
      
          def __init__(self, *args, **kw):
              super(UserProfileForm, self).__init__(*args, **kw)
              self.fields['first_name'].initial = self.instance.user.first_name
              self.fields['last_name'].initial = self.instance.user.last_name
      
              self.fields.keyOrder = [
                  'first_name',
                  'last_name',
                  ...some_other...
                  ]
      
          def save(self, *args, **kw):
              super(UserProfileForm, self).save(*args, **kw)
              self.instance.user.first_name = self.cleaned_data.get('first_name')
              self.instance.user.last_name = self.cleaned_data.get('last_name')
              self.instance.user.save()
      
          class Meta:
              model = UserProfile
      

      【讨论】:

      【解决方案4】:

      我今天偶然发现了这个,经过一番谷歌搜索后,我发现了一个我认为更简洁的解决方案:

      #in forms.py
      class UserForm(forms.ModelForm):
          class Meta:
              model = User
              fields = ["username", "email"]
      
      class UserProfileForm(forms.ModelForm):
          class Meta:
              model = UserProfile
      
      #in views.py
      def add_user(request):
          ...
          if request.method == "POST":
              uform = UserForm(data = request.POST)
              pform = UserProfileForm(data = request.POST)
              if uform.is_valid() and pform.is_valid():
                  user = uform.save()
                  profile = pform.save(commit = False)
                  profile.user = user
                  profile.save()
                  ....
          ...
      
      #in template
      <form method="post">
          {{ uform.as_p }}
          {{ pform.as_p }}
          <input type="submit" ...>
      </form>
      

      Source

      【讨论】:

      • 这是另一种解决方案,但您无法根据需要对字段进行排序。例如,我有一个 title 字段,它应该在 first_name 和 last_name 之前,但仍然是 pform 的一部分。
      • Natim,你可以——但需要你自己动手:)
      • 您可以指定字段的顺序...正如ns-keip所说...只要您自己进行渲染..docs.djangoproject.com/en/1.8/topics/forms/…
      • 如何让密码 1 和密码 2 用于用户注册?只有“密码”可用。
      【解决方案5】:

      为什么不在后端有两个模型表单,然后在模板中将它们显示为一个表单?从 UserProfileForm 中删除名称字段并为用户对象创建第二个模型表单?

      【讨论】:

      • 这不是一个坏主意。但是只有一种形式更方便。
      • 我猜有不同的方法。我之所以选择上面描述的内容,正是因为使用多个 Django 表单对象更方便,因此它们可以相互独立地重复使用(并且处理比您上面的处理更干净(恕我直言))。需要明确的是,我不是在谈论一个页面上的多个 HTML 表单。对用户来说,它看起来像是一种形式。
      【解决方案6】:

      这就是我在当前主干中的做法(修订版:11804)。 Natim 的解决方案对我不起作用。

      admin.py:

      class ProfileAdmin(admin.ModelAdmin):
          form = ProfileForm
      
          def save_model(self, request, obj, form, change):
              obj.user.first_name = form.cleaned_data['first_name']
              obj.user.last_name = form.cleaned_data['last_name']
              obj.user.save()
              obj.save()
      

      forms.py:

      class ProfileForm(forms.ModelForm):
          first_name = forms.CharField(max_length=256)
          last_name = forms.CharField(max_length=256)
      
          def __init__(self, *args, **kwargs):
              super(ProfileForm, self).__init__(*args, **kwargs)
              try:
                  self.fields['first_name'].initial = self.instance.user.first_name
                  self.fields['last_name'].initial = self.instance.user.last_name
              except User.DoesNotExist:
                  pass
      
          class Meta:
               fields = ['first_name', 'last_name', ...etc.]
      

      【讨论】:

      • 但是使用您的 ProfileForm,您无法保存配置文件。我的不修改管理员。但是你的可以,但是没有管理员就不能使用。
      • 它确实使用obj.save() 保存配置文件。您正确的是它仅在管理员中有效。我必须把它构建到那个里面。让它在你的应用程序中工作。您应该将逻辑从管理员移到表单中。就像您对 save 方法所做的那样。
      【解决方案7】:

      当您将两个模型合并为一个表单时,您在文档中找不到任何信息是正常的。

      另外,很明显您可以:创建两个模型表单,一个用于用户,另一个用于用户配置文件。将 userprofile modelform 设置为仅显示名字和姓氏。将两个表单放在同一个模板中的单个&lt;form&gt; 标记中。提交时,调用各个表单的保存方法。

      【讨论】:

      • 是的,但实际上使用两种形式并不是很直接...使用此解决方案,您无法按需要对字段进行排序并继续使用{{ form }}。使用我提供的解决方案,您可以继续使用表单框架做任何您想做的事情。
      • 我只是不喜欢在一个模型表单中合并两个模型的想法。除了我的主观意见外,我对你的解决方案没有具体的反对意见,似乎两种解决方案都各有利弊。随意使用;)
      • 我同意你的观点,但是你寻找这个特定问题的观点是关于你的观点。 UserProfile 和 User 模型密切相关。对我来说,UserProfile 模型只是向 User 模型添加一些缺失字段的一种方式。当您想要更新您的个人资料时,您想要更新所有这些字段,无论它们是在 UserProfile 还是 User 模型中,因为它们组合在一起以存储有关用户的属性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-13
      • 2017-10-12
      • 1970-01-01
      • 2012-07-18
      • 1970-01-01
      • 2012-07-25
      • 2013-04-06
      相关资源
      最近更新 更多