Python 如何在Django中使用单个表单创建用户和配置文件?

Python 如何在Django中使用单个表单创建用户和配置文件?,python,django,django-3.0,Python,Django,Django 3.0,我已在models.py中创建了一个Clients模型,该模型旨在作为客户(用户)配置文件 此模型通过名为user的OneToOneField连接到Django用户 我创建了一个表单,可以在forms.py中向客户机模型添加数据: from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from djang

我已在
models.py
中创建了一个
Clients
模型,该模型旨在作为客户(用户)配置文件

此模型通过名为
user
的OneToOneField连接到Django用户

我创建了一个表单,可以在
forms.py
中向
客户机
模型添加数据:

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.core.validators import RegexValidator

class SignUpForm(UserCreationForm):
    first_name = forms.CharField(max_length=30, label="Primeiro Nome")
    last_name = forms.CharField(max_length=30, label="Apelido")
    address = forms.CharField(max_length=200, label="Morada")
    nif = forms.CharField(max_length=9, label="NIF", validators=[RegexValidator(r'^\d{1,10}$')])
    mobile = forms.CharField(max_length=9, label="Telemóvel", validators=[RegexValidator(r'^\d{1,10}$')])
    email = forms.CharField(max_length=200, label="Email")

    class Meta:
        model = User
        fields = ('username', 'password1', 'password2', 'first_name', 'last_name', 'address', 'nif', 'mobile', 'email')
如何通过这个表单添加
用户名
密码
字段,以便通过OneToOneField创建连接到此配置文件的用户

编辑

以上文件的新版本。现在,它创建了用户,但是
客户端的所有其他字段都被传递为空

我的
视图.py

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.first_name = form.cleaned_data.get('first_name')
            user.last_name = form.cleaned_data.get('last_name')
            user.address = form.cleaned_data.get('address')
            user.nif = form.cleaned_data.get('nif')
            user.mobile = form.cleaned_data.get('mobile')
            user.email = form.cleaned_data.get('email')
            user.save()
            raw_password = form.cleaned_data.get('password1')
            user = authenticate(username=user.username, password=raw_password)
            login(request, user)
            return redirect('clientes')
    else:
        form = SignUpForm()
    return render(request, 'backend/new_client.html', {'form': form})

您添加的字段只是常规表单字段,django不知道在哪里保存这些值。因此,您需要重写表单的
save()
方法或将它们保存在视图中。以下是如何在视图中保存它们,因为这是您开始执行的操作:

if form.is_valid():
    user = form.save()  # this creates the user with first_name, email and last_name as well!
    user.refresh_from_db()  # load the profile instance created by the signal
    user.clients.address = form.cleaned_data.get('address')
    user.clients.nif = form.cleaned_data.get('nif')
    user.clients.mobile = form.cleaned_data.get('mobile')
    user.clients.save()
    login(request, user)
    return redirect('clientes')
注意:我不使用视图中的
名字
姓氏
电子邮件
执行任何操作,它们是
用户
模型的字段,因此在执行
表单.save()
操作时,它们将自动保存。您应该将它们从
客户机
模型中删除

注2:将
客户机
模型重命名为
客户机
将使代码更具可读性。您应该始终为您的模型使用单数。通过这种方式,您可以执行
user.client.address
,这比
user.clients.address
更有意义,因为它是一对一字段

或者,您可以覆盖表单的
save()
方法,这是我更喜欢的方法,因为我认为视图不应该关心如何保存用户的配置文件:

# in SignupForm(UserCreationForm):
def save(self, commit=True):
    user = super().save(commit)  # this creates the new user
    if commit:
        user.refresh_from_db()  # not sure if this is needed
        user.clients.nib = self.cleaned_data.get('nib')
        user.clients.address = self.cleaned_data.get('address')
        user.clients.mobile = self.cleaned_data.get('mobile')
        user.clients.save()
    return user

如果你用谷歌搜索你的问题,你会找到一个教程,它准确地显示了你需要什么:子类化(来自django.contrib.auth.forms),这样创建用户的所有功能都已经存在。@dirkgroten我遵循了那个教程,但数据没有保存。但这不是你在这里展示的代码。子类化
UserCreationForm
是正确的方法,因此回到这一点,按照教程所示编写代码,并用该代码编辑您的问题。教程实际上说表单不会自动保存额外的字段。您需要在视图中执行此操作(实际上我会在表单的
save()
方法中执行)@dirkgroten我再次遵循了教程。我现在可以保存用户,但所有其他字段都会被传递为空。我更新问题。向我们展示你的观点
# in SignupForm(UserCreationForm):
def save(self, commit=True):
    user = super().save(commit)  # this creates the new user
    if commit:
        user.refresh_from_db()  # not sure if this is needed
        user.clients.nib = self.cleaned_data.get('nib')
        user.clients.address = self.cleaned_data.get('address')
        user.clients.mobile = self.cleaned_data.get('mobile')
        user.clients.save()
    return user