Django 扩展用户模型 - 从模型继承配置文件表单

时间:2021-03-10 05:36:37

标签: python django

我正在按照教程在 Django 3.1.7 中执行此操作。

我在这里遇到的问题是我被迫在我的配置文件表单定义中重复我的配置文件模型。

我想在我的 forms.py 中使用 forms.ModelForm 来继承我的配置文件模型并自动生成表单。当它已经在我的模型中定义时,必须在 forms.py 中再次拼写所有内容似乎是多余的。但我不确定如何使用这种架构来做到这一点。

我试过这种方法: https://stackoverflow.com/a/2213802/4144483 但问题在于用户表单不完整 - 模型用户不存在“password1”和“password2”。对于用户注册来说,这不是一个好的解决方案。我似乎必须以某种方式使用 UserCreationForm。

#models.py 
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()


#forms.py
rom django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User

class SignUpForm(UserCreationForm):
    birth_date = forms.DateField(help_text='Required. Format: YYYY-MM-DD')

    class Meta:
        model = User
        fields = ('username', 'birth_date', 'password1', 'password2', )



#views.py
from django.contrib.auth import login, authenticate
from django.shortcuts import render, redirect
from mysite.core.forms import SignUpForm

def signup(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            user = form.save()
            user.refresh_from_db()  # load the profile instance created by the signal
            user.profile.birth_date = form.cleaned_data.get('birth_date')
            user.save()
            raw_password = form.cleaned_data.get('password1')
            user = authenticate(username=user.username, password=raw_password)
            login(request, user)
            return redirect('home')
    else:
        form = SignUpForm()
    return render(request, 'signup.html', {'form': form})

1 个答案:

答案 0 :(得分:1)

我通常使用 ModelForm 而不是 CreateUserForm 来进行这样的用户注册,并在其中添加 password1 和 password2 字段。另外,我检查它们是否相同。:

forms.py

class UserRegistrationForm(forms.ModelForm):
    password = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput)
    email = forms.EmailField(label='Email')
    date_of_birth = forms.DateField(widget=forms.widgets.DateInput(attrs={'type': 'date'}))
    class Meta:
        model = User
        fields = ['username', 'first_name', 'last_name', 'email',
                 ] #these ordering will be as follow in html form

    def clean_password2(self):
        cd = self.cleaned_data
        if cd['password'] != cd['password2']:
            raise forms.ValidationError("Passwords don't match")
        return cd['password2']

然后在视图中,我创建一个用户和他们的个人资料,并以加密形式保存密码,并链接他们的个人资料。

views.py

def register(request):
    u_form = UserRegistrationForm(data=request.POST or None)
    p_form = ProfileForm(data=request.POST or None, files=request.FILES or None)
    if u_form.is_valid() and p_form.is_valid():
        new_user = u_form.save(commit=False)
        new_user.set_password(u_form.cleaned_data['password']) #this saves password in encrypted form instead of raw password
        new_user.save()
        profile = p_form.save(commit=False)
        profile.user = new_user
        profile.save()
        return render(request, 'accounts/register_done.html', {'new_user': user})
    return render(request, 'accounts/register.html', {'user_form': u_form, 'profile_form':p_form})

你可以随意修改它。