【问题标题】:Django - How to extend Custom User using CreateViewDjango - 如何使用 CreateView 扩展自定义用户
【发布时间】:2019-09-11 10:38:44
【问题描述】:

我想使用 CreateView 创建用户注册表单。但是,我不知道如何在 view.py 中将 User Model 与 Profile Model 结合起来

我的环境 ・Django2.2

这是我写的代码:

▪️model.py

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email address'), unique=True)
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    gender = models.CharField(max_length=20, blank=True)

▪️form.py

class UserCreateForm(UserCreationForm):

    class Meta:
        model = User
        if User.USERNAME_FIELD == 'email':
            fields = ('email',)
        else:
            fields = ('username', 'email')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields.values():
            field.widget.attrs['class'] = 'form-control'

class ProfileForm(forms.ModelForm):
    CHOICES = (
        ('female', 0,),
        ('male', 1,),
        ('not_applicable', 2,)
    )
    gender = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES, required=False)

▪️View.py

from django.views import generic
from .forms import UserCreateForm

class UserCreate(generic.CreateView):
    template_name = 'accounts/create.html'
    form_class = UserCreateForm

    def form_valid(self, form):
        user = form.save(commit=False)
        user.is_active = False
        user.save()

        current_site = get_current_site(self.request)
        domain = current_site.domain
        context = {
            'protocol': 'https' if self.request.is_secure() else 'http',
            'domain': domain,
            'token': dumps(user.pk),
            'user': user,
        }

        subject_template = get_template('accounts/mail/create/subject.txt')
        subject = subject_template.render(context)

        message_template = get_template('accounts/mail/create/message.txt')
        message = message_template.render(context)

        user.email_user(subject, message)
        return redirect('accounts:user_create_done')

▪️create.html

<form action="" method="POST">
    {{ form.non_field_errors }}
            {% for field in form %}
                    <p>{{ field }} {{ field.errors }}</p>
            {% endfor %}
    {% csrf_token %}
    <button type="submit" class="button-submit">submit</button>
</form>

但是,这只能显示用户列(电子邮件,仅密码)。但我想显示用户列和个人资料列(电子邮件、密码、名字、姓氏、性别)。

这可能吗?

【问题讨论】:

    标签: django


    【解决方案1】:

    您应该在自己的 CustomUserModel 中继承 AbstractBaseUser,添加所需的其他字段,然后在您的 settings.py 文件中覆盖 AUTH_USER_MODEL=yourapp.CustomUserModel

    this 也值得一看。

    【讨论】:

      【解决方案2】:

      UserCreationFormMeta 中的fields 列表应包含您需要显示的所有字段。您还应该在UserCreationFrom 中添加配置文件字段并手动更新配置文件。另外,请更改表单名称,以区别于 django 的 UserCreateForm

      此外,请确保无论何时拨打user.profile,都会为用户创建个人资料。

      # models.py
      # add the below line in the end of the file.
      User.profile = property(lambda u: Profile.objects.get_or_create(user=u)[0])
      
      

      更新您的表单。

      # forms.py
      
      class CustomUserCreateForm(UserCreationForm):
          CHOICES = (
              ('female', 0,),
              ('male', 1,),
              ('not_applicable', 2,)
          )
          gender = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES, required=False)
      
          class Meta:
              model = User
              if User.USERNAME_FIELD == 'email':
                  fields = ('email',)
              else:
                  fields = ('username', 'email')
              fields += ('password', 'first_name', 'last_name', 'gender')
      
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              for field in self.fields.values():
                  field.widget.attrs['class'] = 'form-control'
      

      在你看来,你可以将gender的值保存在user.profile中。

      class UserCreate(generic.CreateView):
          template_name = 'accounts/create.html'
          form_class = CustomUserCreateForm
      
          def form_valid(self, form):
              user = form.save(commit=False)
              user.is_active = False
              user.save()
      
              # get the value of gender and save to user.profile
              gender = form.cleaned_data.get("gender")
              profile = user.profile  # this will get_or_create the profile instance
              profile.gender = gender
              profile.save()
      
              current_site = get_current_site(self.request)
              domain = current_site.domain
              context = {
                  'protocol': 'https' if self.request.is_secure() else 'http',
                  'domain': domain,
                  'token': dumps(user.pk),
                  'user': user,
              }
      
              subject_template = get_template('accounts/mail/create/subject.txt')
              subject = subject_template.render(context)
      
              message_template = get_template('accounts/mail/create/message.txt')
              message = message_template.render(context)
      
              user.email_user(subject, message)
              return redirect('accounts:user_create_done')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-24
        • 2011-02-22
        • 2011-08-08
        • 1970-01-01
        相关资源
        最近更新 更多