1

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

class Clients(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=30, verbose_name="Primeiro Nome")
    last_name = models.CharField(max_length=30, verbose_name="Apelido")
    address = models.CharField(max_length=200, verbose_name="Morada")
    nif = models.CharField(max_length=9, verbose_name="NIF", validators=[RegexValidator(r'^\d{1,10}$')], primary_key=True)
    mobile = models.CharField(max_length=9, verbose_name="Telemóvel", validators=[RegexValidator(r'^\d{1,10}$')])
    email = models.CharField(max_length=200, null=True, verbose_name="Email")
    avatar = models.ImageField(null=True)

    def __str__(self):
        return "%s %s" % (self.first_name, self.last_name)

    class Meta:
        verbose_name_plural = "Clientes"

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

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

我创建了一个能够向Clients模型添加数据的表单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')

我怎样才能通过这个单一的表单添加一个usernamepassword字段,以便通过 OneToOneField 创建一个连接到此配置文件的用户?

编辑

上述文件的新版本。现在,它创建了用户,但所有其他字段都为Clients空。

我的views.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})
4

1 回答 1

1

您添加的字段只是常规表单字段,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')

注意:我对 不做任何事情first_namelast_name并且email在视图中,它们是User模型的字段,所以当你这样做时它们已经被自动保存了form.save()。您应该从Clients模型中删除它们。

注意 2:将Clients模型重命名为Client将使您的代码更具可读性。您应该始终对模型使用单数。这样你就可以做到比一对一的字段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
于 2020-02-18T15:23:20.270 回答