如何在用户在Django中注册后自动将users表链接到另一个表

2024-07-06 18:58:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个电子商务网站,在这个网站上我使用了Django身份验证的功能,允许用户注册和登录。然而,在注册表中,我一次从两个表中获取信息,如下所示。。。 Two tables are, User and Shipping

在我的模型中。py

class Profile (models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    mobileNumber = models.CharField(max_length=13)
    address = models.ForeignKey(Shipping, on_delete=models.DO_NOTHING, default=False)
    guest = models.BooleanField(default=False)

class Shipping(models.Model):
    addressLine1 = models.CharField(max_length=100)
    addressLine2 = models.CharField(max_length=100)
    city = models.CharField(max_length=40)
    postalCode = models.CharField(max_length=5)
    landmark = models.CharField(blank=True, max_length=80)

还有我的表格

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
from store.models import Shipping


class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()
    first_name = forms.CharField()
    last_name = forms.CharField()
    mobile_number  = forms.CharField()

    class Meta:
        model = User
        fields = ['username', 'first_name', 'last_name', 'mobile_number',  'email', 'password1', 'password2']


class AddressRegisterForm(forms.ModelForm):
    class Meta:
        model = Shipping
        fields = ['addressLine1', 'addressLine2', 'city', 'postalCode', 'landmark']

我的信号

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


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


@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
    instance.profile.save()

我的观点。派克

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserRegisterForm
from .forms import AddressRegisterForm
from .models import Profile
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from . import signals
import django.dispatch
# Create your views here.



def register(request):
    if not request.user.username :
        if request.method == 'POST':
            form = UserRegisterForm(request.POST)
            form1 = AddressRegisterForm(request.POST)
            if form.is_valid() and form1.is_valid():
                email = form.cleaned_data.get('email')
                if not User.objects.filter(email=email).exists():
                    username = form.cleaned_data.get('username')
                    messages.success(request, f"The Account created for {username}! You are now able to login.")
                    form1.save()
                    form.save()
                    return redirect('login')
                else:
                    messages.warning(request, f"The email is either invalid or already used to create an account")
        else:
            form1 = AddressRegisterForm()
            form = UserRegisterForm()
        return render (request, 'register.html', {"form":form, "form1":form1})
    else:
        username = request.user.username
        messages.warning(request, f"You are already logged in as {username}!")
        return redirect ('home')

最后,我的模板

{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% load static %}
{% block title %}Register{% endblock %}

{% block content %}

<div class="content-section mb-5">
    <form method="POST">{% csrf_token %}
        <div style="display: flex; width: 100%; justify-content: space-around;">
            <fieldset class="form-group mt-4" style="width: 48%;">
                <legend class="border-bottom mb-4">Register</legend>
                {{ form | crispy }}
            </fieldset>
            <fieldset class="form-group mt-3" style="width: 48%;">
                <legend class="border-bottom mb-4">Shipping info</legend>
                {{ form1 | crispy }}
            </fieldset>
        </div>
        <div class="form-group mt-3">
            <button class="btn btn-outline-info" type="submit">Sign up</button>                
            <small class="text-muted ml-3"><a href="#">Forgot Password?</a></small>
        </div>
        
    </form>
    <div class="border-top pt-3">
        <small class="text-muted">Already have an account? <a href="{% url 'login' %}">Sign in</a></small>
    </div>
</div>

{% endblock %}

我的信息存储在相关的表中,但是,似乎对配置文件表没有影响,仍然是空的

在用户注册后,是否有任何方法可以启动django来链接用户和配置文件表中的地址

任何帮助都将不胜感激, 非常感谢


Tags: djangofromimportdivformmodelsemailrequest
2条回答

您需要在app configurationready()函数中加载信号:

Where should this code live?

Strictly speaking, signal handling and registration code can live anywhere you like, although it’s recommended to avoid the application’s root module and its models module to minimize side-effects of importing code.

In practice, signal handlers are usually defined in a signals submodule of the application they relate to. Signal receivers are connected in the ready() method of your application configuration class. If you’re using the receiver() decorator, import the signals submodule inside ready().

yourapp/apps.py

class YourAppConfig(AppConfig):
    name = "yourapp"
    def ready(self):
        from . import signals

这应该足以在正确的时间记录信号

关于两个问题:

  1. 数据库中的现有用户模型不会得到更新,只会更新新的用户模型。如果数据库处于活动状态或希望保持当前状态,请删除数据库并创建新用户,或添加data migration
  2. 通过信号连接的模型必须在没有任何数据的情况下创建。所以您必须有nullable fields或带有defaults的字段

两种形式

因此,您在HTML中将两个表单作为一个表单发布,这是因为您的表单不共享字段名(主键除外,主键未发布)。为了便于将来参考,您可以使用form prefix来处理重复的字段名,甚至可以将相同的表单用于不同的目的(例如发货地址和帐单地址)

在信号上

信号在事件发生时使用(用户保存,用户登录),这是第三方代码(在本例中为Django)的一部分。但是,当您是创建活动的人时,不需要它们,因为您可以在创建活动的地方做任何您想做的事情

是否登录

正确的测试是: if not request.user.is_authenticated:

关于解决办法

使用一个或多个表单保存相关模型时,应首先创建可以在不存在关系的其他模型的情况下保存的模型。这些是:

  • 模型a外键指向(装运)
  • OneToOneField的模型,其中OneToOneField未定义(用户)

由于该信号,我们的概要文件模型将使用空值创建,但是表单不知道mobile_number属于概要文件模型,因为它是绑定到用户ModelModel表单。它将mobile_number视为一个您将自己处理的字段。让我们这样做:


user = form.save()  # save returns the model instance created
profile = user.profile
profile.mobile_number = form.cleaned_data['mobile_number']

如上所述,我们可以毫无问题地创建地址,然后将其链接到配置文件:

address = form1.save()  # save returns the model instance created
profile.address = address

现在我们可以保存配置文件:

profile.save()

因此,把所有这些放在一起:

def register(request):
    if not request.user.is_authenticated:  # The correct way to test for logged in user
        if request.method == "POST":
            form = UserRegisterForm(request.POST)
            form1 = AddressRegisterForm(request.POST)
            if form.is_valid() and form1.is_valid():
                email = form.cleaned_data.get("email")
                if not User.objects.filter(email=email).exists():
                    username = form.cleaned_data.get("username")
                    messages.success(
                        request,
                        f"The Account created for {username}! You are now able to login.",
                    )
                    user = form.save()
                    profile = user.profile
                    profile.mobile_number = form.cleaned_data['mobile_number']
                    
                    address = form1.save()
                    profile.address = address
                    profile.save()

                    return redirect("login")
                else:
                    messages.warning(
                        request,
                        f"The email is either invalid or already used to create an account",
                    )
        else:
            form1 = AddressRegisterForm()
            form = UserRegisterForm()

        return render(request, "register.html", {"form": form, "form1": form1})
    else:
        username = request.user.username
        messages.warning(request, f"You are already logged in as {username}!")
        return redirect("home")

您可以在“配置文件”模型中添加与发货地址相关的所有字段。 当您想要访问该数据时,您可以简单地使用QuerySet。 在模型中

class Profile (models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    mobileNumber = models.CharField(max_length=13)
    address = models.ForeignKey(Shipping, on_delete=models.DO_NOTHING, default=False)
    guest = models.BooleanField(default=False)
    addressLine1 = models.CharField(max_length=100)
    addressLine2 = models.CharField(max_length=100)
    city = models.CharField(max_length=40)
    postalCode = models.CharField(max_length=5)
    landmark = models.CharField(blank=True, max_length=80)

当您想要访问数据时,只需使用QuerySet即可

相关问题 更多 >