【问题标题】:Not able to authenticate custom user model in Django无法在 Django 中验证自定义用户模型
【发布时间】:2016-02-11 23:52:27
【问题描述】:

我创建了一个Custom User model in Django,您可以在下面看到我的models.py

from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from uuidfield import UUIDField

class User(AbstractUser, Mixin):
    objects = HiddenUserManager()
    USERNAME_FIELD = 'username'
    # REQUIRED_FIELDS = ['email', 'password']
    api_token = UUIDField(auto=True)
    token_created_date = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('email', )  # must have unique email!
        app_label = 'portal'

    def api_token_reset(self):
        self.api_token = UUIDField(auto=True)

我还更改了我的settings.py 文件并添加了这一行:

AUTH_USER_MODEL = 'portal.User'portal 是我的应用程序的名称。

我使用portal.user model 创建了两个superusers,如下图所示:

问题是当我在索引登录页面中输入我的username and password 时,它无法对我进行身份验证。创建模型后,我执行了所有migrations。为什么登录页面无法验证我的身份?

如果我注释掉我的customer user model 并删除这一行AUTH_USER_MODEL = 'portal.User',那么我的登录页面就可以对我进行身份验证。知道我哪里出错了吗?

我的登录视图如下所示:

from django.contrib.auth.views import login
from django.http import HttpResponseRedirect

def login(request, **kwargs):
    return login(request, **kwargs)

有人可以帮我吗?

更新:混合类

class RequireStaffMixinView(RequireAuthMixinView):
    # Override 1) ensure staff
    # @method_decorator(staff_user_required)
    def dispatch(self, *args, **kwargs):
        if not self.request.user.is_staff:
            raise PermissionDenied
        return super(RequireAuthMixinView, self).dispatch(*args, **kwargs

【问题讨论】:

  • 您能否发表您的观点,其中有处理身份验证的逻辑代码,例如authenticate 方法,好吗?
  • user.is_authenticated 正在工作,但我的用户应该是 superuser 才能访问下一页。查看我使用的mixin 类,以确保用户始终使用superuser 访问下一页或提出Permission Denied
  • 混合在 User 模型中的作用是什么?
  • 确保用户模型为superuser,否则提升PermissionDenied
  • 关于登录功能,我使用的是from django.contrib.auth.views import login

标签: django authentication django-models django-templates django-views


【解决方案1】:

要创建自定义用户模型,请按照 django 文档的建议扩展 AbstractBaseUser 模型并将您的自定义字段添加到其中。

另外请注意,由于 Django 对可交换模型的动态依赖特性的限制,您必须确保 AUTH_USER_MODEL 引用的模型是在其应用程序的第一次迁移中创建的(通常称为 0001_initial);否则,您将遇到依赖问题。

models.py

import uuid

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models


class CustomUserManager(BaseUserManager):
    def create_user(self, email, password, **kwargs):
        if not email or not password:
            raise ValueError('User must have a username and password')

        user = self.model(
            email=CustomUserManager.normalize_email(email),
            **kwargs
        )

        user.set_password(password)
        user.save()

        return user

    def create_superuser(self, email, password, **kwargs):
        user = self.create_user(email, password, **kwargs)

        user.is_admin = True
        user.is_staff = True
        user.save()

        return user


class User(AbstractBaseUser):
    first_name = models.CharField(max_length=255, null=False)
    last_name = models.CharField(max_length=255, null=False)
    email = models.EmailField(null=False, unique=True)
    is_active = models.BooleanField(default=True)
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)
    is_staff = models.BooleanField(default=False)

    # Add custom fields here
    api_token = models.UUIDField(default=uuid.uuid4, editable=False)
    token_created_date = models.DateTimeField(auto_now_add=True)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    def get_full_name(self):
        return self.first_name + " " + self.last_name

    def get_short_name(self):
        return self.first_name

    def has_perm(self, perm, obj=None):
        return self.is_staff

    def has_module_perms(self, app_label):
        return self.is_staff

    def api_token_reset(self):
        self.api_token = models.UUIDField(default=uuid.uuid4, editable=False)

    class Meta:
        ordering = ('created_on',)
        db_table = 'users'

    def __unicode__(self):
        return self.get_full_name()

并将以下代码添加到您的 settings.py 中。注意-tester 是我的应用程序的名称

AUTH_USER_MODEL = 'tester.User'

现在运行以下命令 -

python manage.py makemigrations
python manage.py migrate

现在您应该可以毫无问题地登录 django 管理员了。

如果要创建自定义登录页面,请在视图中检查用户是否为管理员 -

views.py

from django.contrib.auth import authenticate, login
from django.contrib.auth.forms import AuthenticationForm
from django.core.urlresolvers import reverse_lazy
from django.http import HttpResponseRedirect
from django.views.generic import FormView


class LoginView(FormView):
    form_class = AuthenticationForm
    template_name = 'login.html'

    def form_valid(self, form):
        username = form.cleaned_data['username']
        password = form.cleaned_data['password']
        user = authenticate(username=username, password=password)

        # Check here if the user is an admin
        if user is not None and user.is_active and user.is_staff:
            login(self.request, user)
            return HttpResponseRedirect(self.success_url)
        else:
            return self.form_invalid(form)

登录.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
<form method="post">
    {%  csrf_token %}
    {{ form }}
    <input type="submit" value="Submit">
</form>
</body>
</html>

urls.py

from django.conf.urls import url

from .views import LoginView

urlpatterns = [
    url(r'^login/$', LoginView.as_view(), name='login'),
]

【讨论】:

  • 感谢@Utkarsh 提供如此详尽的答案。我会调查并接受。
  • 我现在正在旅行,所以没时间再看这个问题。不过我给了你 50 分 :) 你的回答肯定很有帮助
【解决方案2】:

不知道如何,但我添加了 is_active ,is_admin,is_staff ,is_superuser 作为 true 是超级用户创建功能在创建用户中将 is_active 更改为 true 并在 settings.py 中添加了上面指定的后端,它开始工作你只需要创建在所有这些更改之后,具有新迁移的新超级用户和新数据库。它应该工作......

创建超级用户功能:

 def create_superuser(self,email, user_name, address, password, **other_fields):
        user = self.creat_user(email,user_name,address ,password=password,**other_fields)
        user.is_admin = True
        user.is_active = True
        user.is_staff = True
        user.is_superuser = True
        user.save()

        return user

创建用户函数

class NewUser(AbstractBaseUser,PermissionsMixin):
    alphanumeric = RegexValidator(r'^[0-9a-zA-Z]*$', message='Only alphanumeric characters are allowed.') 
    email = models.EmailField(_('Enter Email'),unique=True)
    user_name = models.CharField(max_length=20, unique=True, validators=[alphanumeric])
    address= models.TextField(_(
        'enter Address'),max_length=500,blank=True)

    is_staff = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    objects =CustomeAccountManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['user_name','address']

    def __str__(self):
        return self.email

【讨论】:

    猜你喜欢
    • 2015-03-08
    • 1970-01-01
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 2012-05-05
    • 2016-10-02
    • 2021-01-09
    • 2011-11-14
    相关资源
    最近更新 更多