python Django使用用户注册表

问题描述

我正在用 django 创建一个艺术市场。我为配置文件设置了注册和自动创建信号。将在此应用程序上注册的用户分为三种类型:艺术家、赞助人和经纪人(我称之为 user_status。)我希望用户在注册表单上选择这三个字段之一。我已经到了这样的地步,reg 表单有选择字段和选项,用户可以选择一个,表单保存以创建用户和配置文件,但是当我进入管理时,配置文件没有选择的“user_status” .

我知道非常不鼓励在注册时捆绑配置文件模型字段,但我希望只有这一字段是可选的,因为它会对网站如何查找用户产生重大影响。我读过 (here) 说要在注册时正确填写个人资料字段会涉及很多烦人的自定义。这是真的吗?

我认为如果有解决方案,它会在 Signals.py 上,但我不确定。

在signals.py中输入:

user_status='Patron',

我可以用 instance.get('user_status') 之类的东西替换“赞助人”吗?我知道这里也有一些叫做“默认值”的东西,但我不熟悉。

user/signals.py

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:

        # This functions but cannot get it to grab the form chosen field from the user.
        # just default creates status as patron for now :(
        Profile.objects.update_or_create(
            user=instance,user_status='Patron',)


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

user/forms.py

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

from users.models import Profile

STATUS_CHOICES = (
    ('Artist','Artist'),('Patron','Patron'),('Broker','Broker')
)


class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()
    user_status = forms.ChoiceField(choices=STATUS_CHOICES)

    class Meta:
        model = User
        fields = ['username','email','user_status','password1','password2']

users/views.py

from django.shortcuts import render,redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm


def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            messages.success(request,f'Hello {username}! Your account has been created. You are now ready to log in.')
            return redirect('login')
    else:
        form = UserRegisterForm()

    return render(request,'users/register.html',{'form': form})


@login_required
def profile(request):
    return render(request,'users/profile.html')

user/models.py

class Profile(models.Model):
    STATUS_CHOICES = (
        ('Artist','Broker')
    )
    user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
    user_slug = models.SlugField(blank=True)
    image = models.ImageField(default='default.jpg',upload_to='profile_pics')
    user_status = models.CharField(max_length=100,choices=STATUS_CHOICES)

    def __str__(self):
        return f'{self.user.username} Profile'

修改反映第一条建议:

Views.py

def register(request):
    if request.method == 'POST':

        # create profile object but don't save it to db
        profile = ProfileSetupForm.save(request.POST)
        profile = profile_setup_form.save(commit=False)

        user_form = UserRegisterForm(request.POST)

        if user_form.is_valid():
            # create user object
            user = user_form.save(commit=False)
            # set profile attribute of user object
            user.profile = profile
            # save user - calls post_save
            user.save()

            username = user.username
            messages.success(request,f'Hello {username}! Your account has been created. You are now ready to log in.')
            return redirect('login')
    else:
        user_form = UserRegisterForm()
        profile_setup_form = ProfileSetupForm()

    return render(
        request,{
            'user_form': user_form,'profile_setup_form': profile_setup_form
        }
    )

signals.py

@receiver(post_save,**kwargs):
    if created:
        Profile.objects.update_or_create(
            user=instance,user_status=instance.profile.user_status,)

register.html

{% extends "blog/base.html" %}
{% load crispy_forms_tags %}

{% block content %}
    <div class="content-section">
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Join Today</legend>
                {{ user_form|crispy }}
                {{ profile_setup_form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Sign Up</button>
            </div>
        </form>
        <div class="border-top pt-3">
            <small class="muted">
                Already have an account? <a class="ml-2" href="{% url 'login' %}">Sign In</a>
            </small>
        </div>
    </div>
{% endblock content %}

错误代码

Traceback (most recent call last):
  File "/Users/Tom/Desktop/art_project/art_env/lib/python3.8/site-packages/django/core/handlers/exception.py",line 47,in inner
    response = get_response(request)
  File "/Users/Tom/Desktop/art_project/art_env/lib/python3.8/site-packages/django/core/handlers/base.py",line 181,in _get_response
    response = wrapped_callback(request,*callback_args,**callback_kwargs)
  File "/Users/Tom/Desktop/art_project/users/views.py",line 12,in register
    profile = ProfileSetupForm.save(user_status,request.POST)
  File "/Users/Tom/Desktop/art_project/art_env/lib/python3.8/site-packages/django/forms/models.py",line 451,in save
    if self.errors:

Exception Type: AttributeError at /register/
Exception Value: 'DeferredAttribute' object has no attribute 'errors'

这里是错误代码,如果我把“user_status”去掉,所以这是你建议的代码:

Traceback (most recent call last):
  File "/Users/Tom/Desktop/art_project/art_env/lib/python3.8/site-packages/django/core/handlers/exception.py",in register
    profile = ProfileSetupForm.save(request.POST)
  File "/Users/Tom/Desktop/art_project/art_env/lib/python3.8/site-packages/django/forms/models.py",in save
    if self.errors:

Exception Type: AttributeError at /register/
Exception Value: 'QueryDict' object has no attribute 'errors'

调整后的 forms.py 文件

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

from users.models import Profile

STATUS_CHOICES = (
    ('Artist','Broker')
)


class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()
    # user_status = forms.ChoiceField(choices=STATUS_CHOICES)

    class Meta:
        model = User
        fields = ['username','password2']


class ProfileSetupForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['user_status']

根据评论进行调整的当前 views.py 文件

from django.shortcuts import render,redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm,ProfileSetupForm


def register(request):
    if request.method == 'POST':

        # create profile object but don't save it to db
        profile_setup_form = ProfileSetupForm.save(request.POST)
        profile = profile_setup_form.save(commit=False)

        user_form = UserRegisterForm(request.POST)

        if user_form.is_valid():
            # create user object
            user = user_form.save(commit=False)
            # set profile attribute of user object
            user.profile = profile
            # save user - calls post_save
            user.save()

            username = user.username
            messages.success(request,'profile_setup_form': profile_setup_form
        }
    )

解决方法

我会在您的注册页面上包含另一个表格,尽管这只是作为解决方案的建议。

forms.py

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

from user_status.models import Profile

STATUS_CHOICES = (
    ('Artist','Artist'),('Patron','Patron'),('Broker','Broker')
)


class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()
    # user_status = forms.ChoiceField(choices=STATUS_CHOICES)

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


class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['user_status']

views.py

from django.shortcuts import render,redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm,ProfileForm


def register(request):
    if request.method == 'POST':

        # create profile object but don't save it to db
        profile_form = ProfileForm(request.POST)
        profile = profile_form.save(commit=False)

        user_form = UserRegisterForm(request.POST)

        if user_form.is_valid():
            # create user object
            user = user_form.save(commit=False)
            # set profile attribute of user object
            user.profile = profile
            # save user - calls post_save
            user.save()
            
            username = user.username
            messages.success(request,f'Hello {username}! Your account has been created. You are now ready to log in.')
            return redirect('login')
    else:
        user_form = UserRegisterForm()
        profile_form = ProfileForm()


    return render(
        request,'users/register.html',{
            'user_form': user_form,'profile_form': profile_form
        }
    )


@login_required
def profile(request):
    return render(request,'users/profile.html')

signals.py

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:

        # can now set user_status attribute
        Profile.objects.update_or_create(
            user=instance,user_status=instance.profile.user_status,)


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

我不知道您的 register.html 页面是什么样的,但您可以通过以下方式显示这些表单作为示例。

register.html

<h1>Registration Page</h1>

<form action="/register" method="POST">
    {% csrf_token %}

    {{ user_form.as_p }}

    {{ profile_form.as_p }}

    <input type="submit" value="Register"></input>
</form>

如果您想让用户在注册时也包含这些内容,您可以在 profile_form 中包含更多字段,例如用户的图片。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...