首页 > 解决方案 > 匿名用户在自定义用户模型中没有属性 _meta

问题描述

我已经面对这个问题很长时间了,我已经完成了实验。我是 Django 的新手。

我一直在使用自定义用户模型,但由于某种原因,此注册表单无法正常工作。我无法使用 login() 方法登录,尽管它可以很好地保存数据。此外,登录表单不允许超级用户以外的任何其他用户登录。

这是错误:

AttributeError at /register/
'AnonymousUser' object has no attribute '_meta'
Request Method: POST
Request URL:    http://127.0.0.1:8000/register/
Django Version: 2.2.4
Exception Type: AttributeError
Exception Value:    
'AnonymousUser' object has no attribute '_meta'
Exception Location: C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\utils\functional.py in inner, line 257
Python Executable:  C:\Users\hello\AppData\Local\Programs\Python\Python37-32\python.exe
Python Version: 3.7.4

追溯:

File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\views\generic\base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\views\generic\base.py" in dispatch
  97.         return handler(request, *args, **kwargs)
File "D:\authen\authentica\views.py" in post
  40.                 login(request, user)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\contrib\auth\__init__.py" in login
  126.     request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\utils\functional.py" in inner
  257.         return func(self._wrapped, *args)

Exception Type: AttributeError at /register/
Exception Value: 'AnonymousUser' object has no attribute '_meta'

这是代码:

模型.py

from django.db import models
from django.conf import settings
from django.contrib.auth import get_user_model 
from django.forms import ModelForm
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin

class CustomUserManager(BaseUserManager):
    use_in_migrations = True   
    def create_user(self, email, name ,password=None,is_active= True, is_staff=False, is_admin=False):
        if not name:
            raise ValueError("Users must've a name")
        if not email:
            raise ValueError("Users must've a email")
        if not password:
            raise ValueError("User must've a password")
        user_obj= self.model(
            email=self.normalize_email(email) ,
            name= name
        )
        user_obj.set_password(password)    # Change password for the User
        user_obj.staff= is_staff
        user_obj.admin= is_admin
        user_obj.active= is_active
        user_obj.save(using =self._db)
        return user_obj 

    def create_staffuser(self,email, name ,password=None):
        user= self.create_user(
            email,
            name,
            password=password,
            is_staff= True
        )
        return user

    def create_superuser(self,email, name ,password=None, **extra_fields):
        extra_fields.setdefault('is_superuser', True)
        user = self.create_user(
            email,
            name,
            password=password,
        )
        user.staff = True
        user.admin = True
        user.save(using=self._db)
        return user

class CustomUser(AbstractBaseUser, PermissionsMixin):
    name    = models.CharField(max_length=255)
    email   = models.CharField(max_length=254, unique=True)
    active  = models.BooleanField(default= True)
    staff   = models.BooleanField(default= False)
    admin   = models.BooleanField(default= False)
    timestamp= models.DateTimeField(auto_now_add=True)
    USERNAME_FIELD  ='email'
    REQUIRED_FIELDS= []

    objects= CustomUserManager()

    def __str__(self):
        return self.email

    def get_full_name(self):
        return self.email, self.name

    def has_perm(self, perm, obj=None):
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin

    @property
    def is_active(self):
        return self.active

视图.py

class RegisterView(TemplateView):
    template_name= 'authentica/register.html'
    def get(self, request):
        user= request.user
        if user.is_authenticated:
            return redirect('home')
        else:
            form = RegisterForm()
            return render(request, self.template_name, {'form': form})

    def post(self, request):
        if request.POST:
            form = RegisterForm(request.POST)
            if form.is_valid():
                form.save()
                email = form.cleaned_data.get('email')
                password = form.cleaned_data.get('password')
                user = authenticate(email=email ,password=password) #django built in authentication
                login(request, user)
                return redirect('home') 
        else:
            form = RegisterForm()
        return render(request, self.template_name, {'form': form})

表格.py

class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)

class Meta:
    model = CustomUser
    fields = ('email', 'name')

# def clean_name(self):
#     name= self.cleaned_data.get('name')
#     qs= CustomUser.objects.get('name')
#     if qs.exists():
#         raise forms.ValidationError('Name is taken')
#     return name

def clean_email(self):
    email = self.cleaned_data.get('email')
    qs = CustomUser.objects.filter(email=email)
    if qs.exists():
        raise forms.ValidationError("email is taken")
    return email

def clean_password2(self):
    # Check that the two password entries match
    password1 = self.cleaned_data.get("password1")
    password2 = self.cleaned_data.get("password2")
    if password1 and password2 and password1 != password2:
        raise forms.ValidationError("Passwords don't match")
    return password2

标签: django

解决方案


您没有为用户保存密码。您的自定义是RegisterForm只保存字段和.ModelFormCustomUseremailname

因此,当您是authenticate()您的用户时,这将失败并返回None.

您的下一步是针对login()用户,这会None产生您看到的错误。

继承自django.contrib.auth.forms.UserCreationForm而不是ModelForm. 这将为您节省大量代码(例如,您不必定义password1andpassword2字段,也不必定义clean_password2)并正确保存您的用户。


推荐阅读