【问题标题】:why django signal not working with custom User model?为什么 django 信号不适用于自定义用户模型?
【发布时间】:2020-04-17 14:40:43
【问题描述】:

我正在通过User 模型和UserCreationForm 创建一个 Django 注册表单,并自定义了User 模型以适应单个用户定义的字段contact

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 SignUp(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    Contact = models.TextField(max_length=500, blank=True)

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

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

forms.py

​​>
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms
from  .models import SignUp

class SignUpForm(UserCreationForm):
    email = forms.EmailField()
    first_name = forms.CharField(max_length=100)
    last_name = forms.CharField(max_length=100)
#    phone = format()

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')


class CustomSignUpPage(forms.ModelForm):
    Contact = forms.CharField(max_length=10)
    class Meta:
        model = SignUp
        fields = ('Contact', )

views.py

​​>
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
#from django.contrib.auth.forms import UserCreationForm
from .forms import SignUpForm, CustomSignUpPage

def home(request):
   return render(request, 'authenticate\home.html', {})

def login_user(request):
   if request.method == 'POST':
      username = request.POST['username']
      password = request.POST['password']
      user = authenticate(request, username=username, password=password)
      if user is not None:
         login(request, user)
         messages.success(request, ('login success'))
         return redirect('home')
      else:
         messages.success(request, ('error while login, please try again'))
         return redirect('login')
   else:
      return render(request, 'authenticate\login.html', {})

def logout_user(request):
   logout(request)
   messages.success(request, ('logout successful'))
   return redirect('home')

# def register_user(request):
#    if request.method == "POST":
#       form = UserCreationForm(request.POST)
#       if form.is_valid():
#          form.save()
#          username = form.cleaned_data['username']
#          password = form.cleaned_data['password1']
#          user = authenticate(request, username=username, password=password)
#          login(request, user)
#          messages.success(request, ('Registration successful'))
#          return redirect('home')
#    else:
#       form = UserCreationForm()
#    return render(request, 'authenticate\\register.html', context={'form': form})

def register_user(request):
   if request.method == "POST":
      form = SignUpForm(request.POST)
      cus_form = CustomSignUpPage(request.POST)
      if form.is_valid() and cus_form.is_valid():
         save1 = form.save()
         save1.refresh_from_db()
         cus_form = CustomSignUpPage(request.POST, instance=save1.AUTHENTICATION)
         cus_form.full_clean()
         cus_form.save()
         username = form.cleaned_data['username']
         password = form.cleaned_data['password1']
         user = authenticate(request, username=username, password=password)
         login(request, user)
         messages.success(request, f'Registration successful')
         return redirect('home')
      else:
         messages.error(request, f'Please correct the error below.')
   else:
      form = SignUpForm()
      cus_form = CustomSignUpPage()

   return render(request, 'authenticate\\register.html', context={'form': form, 'cus_form': cus_form})

但是,我写的信号似乎不起作用。我关注了以下博客:

https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html

每当我填写表格时,我都会收到以下错误:

AttributeError at /auth/register/
'User' object has no attribute 'profile'

以下是完整的 Traceback 日志:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/auth/register/

Django Version: 3.0.5
Python Version: 3.8.2
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'phone_field',
 'AUTHENTICATION']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "C:\Python38\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Python38\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Python38\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\anshu\djago-project\SkoolSkill\AUTHENTICATION\views.py", line 50, in register_user
    save1 = form.save()
  File "C:\Python38\lib\site-packages\django\contrib\auth\forms.py", line 137, in save
    user.save()
  File "C:\Python38\lib\site-packages\django\contrib\auth\base_user.py", line 66, in save
    super().save(*args, **kwargs)
  File "C:\Python38\lib\site-packages\django\db\models\base.py", line 745, in save
    self.save_base(using=using, force_insert=force_insert,
  File "C:\Python38\lib\site-packages\django\db\models\base.py", line 793, in save_base
    post_save.send(
  File "C:\Python38\lib\site-packages\django\dispatch\dispatcher.py", line 173, in send
    return [
  File "C:\Python38\lib\site-packages\django\dispatch\dispatcher.py", line 174, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "C:\Users\anshu\djago-project\SkoolSkill\AUTHENTICATION\models.py", line 17, in save_user_profile
    instance.profile.save()

Exception Type: AttributeError at /auth/register/
Exception Value: 'User' object has no attribute 'profile'

我已经通过以下位置链接将项目上传到谷歌驱动器中,以防万一有人想测试它。

https://drive.google.com/file/d/1COB3BBoRb95a85cLi9k1PdIYD3bmlnc0/view?usp=sharing

我的环境:

Django==3.0.5 蟒蛇3.8.2

不知道是什么错误。请帮忙

【问题讨论】:

    标签: django python-3.x django-forms


    【解决方案1】:

    看起来这个信号正在抛出:

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

    我认为问题在于用户模型没有配置文件字段:https://docs.djangoproject.com/en/3.0/topics/auth/default/#user-objects

    【讨论】:

    • 是的,是那个接收器导致了这个问题。由于我要添加用户定义的表单字段“联系人”。所以,我想为此使用信号。现在我使用了“联系人”而不是“个人资料”,但我遇到了问题。不确定我做的是否正确。
    • 可以访问注册,如果您想访问联系人字段,您可以执行instance.signup 之类的操作,这将是instance.signup.contact 在注册模型上调用保存方法没有任何意义,因为它应该在(另一个信号)之前创建并保存,而您没有更改它。你对这个信号的目标是什么,它应该做什么/改变?
    • 我的目标是通过 forms.py 更新“联系人”字段,这就是我尝试使用信号的原因。我是第一次使用 Signal,我已经实现了我所理解的。如果用户定义的字段“联系人”可以在没有信号的情况下工作,那么这对我也有用。
    • 接下来,我按照您的指示将“instance.signup.save()”替换为“instance.signup.Contact”。因此,这一次,错误移向了第 52 行的 views.py,恰好是“cus_form = CustomSignUpPage(request.POST, instance=request.save1.signup.contact)”。错误是“/auth/register/ 'WSGIRequest' 对象的 AttributeError 没有属性 'save1”。但我使用“save1”来保存表单。请查看原始帖子中的views.py。再次感谢您。
    • 只是您在此评论中写的instance=request.save1.signup.contact 中的一个问题,在更新后的帖子中我没有看到这一行,而且请求也没有得到 save1 变量,这只是一个局部变量
    猜你喜欢
    • 2021-11-13
    • 2013-04-20
    • 2015-10-22
    • 2015-03-23
    • 2020-02-11
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多