创建自定义用户模型的超级用户后无法登录Django管理界面

16

我已经尝试了几个小时,使用成功创建的超级用户登录django管理面板,但无法正确获取用户名/密码组合。

我希望用户只需使用他们的电子邮件作为用户名。我已经尽力复制Django文档这里的示例。我已删除迁移、同步数据库,除了登录到管理面板之外,一切正常。

相关代码: 从models.py

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

class UserManager(BaseUserManager):
    def create_user(self, email, password=None):
        """
        Creates and saves a User with the given email
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=UserManager.normalize_email(email),
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(email,
            password=password
        )

        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user



class User(AbstractBaseUser):
    objects = UserManager()
    date_added = models.DateField(auto_now=False, auto_now_add=True)
    email = models.EmailField(unique=True, db_index=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    def __unicode__(self):
        return self.email

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

    def get_full_name(self):
    # The user is identified by their email address
        return self.email

    def get_short_name(self):
    # The user is identified by their email address
        return self.email

    # On Python 3: def __str__(self):
    def __unicode__(self):
        return self.email

    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

    def is_staff(self):

    # Simplest possible answer: All admins are staff
        return self.is_admin   

来自 admin.py 文件:

from django.contrib import admin
from app.models import Relationship, Event, User
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField


class UserCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required
    fields, plus a repeated password."""

    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('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

    def save(self, commit=True):
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = User

    def clean_password(self):
        return self.initial["password"]





class UserAdmin(UserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm


    list_display = ('email', 'is_admin')
    list_filter = ('is_admin',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Permissions', {'fields': ('is_admin',)}),
    )

    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'password1', 'password2')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()

admin.site.register(User, UserAdmin)
admin.site.unregister(Group)

相关的settings.py代码:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.contrib.auth.middleware.RemoteUserMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'relrem.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'relrem.wsgi.application'

TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'app',
    'south',

    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)

AUTH_USER_MODEL = 'app.User'

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.RemoteUserBackend',
)

创建超级用户并在表格中查看的示例终端输出:

Email: name@sample.com
Password:
Password (again):
Superuser created successfully.

[
{
"pk": 1,
"model": "app.user",
"fields": {
    "is_active": true,
    "last_login": "2013-09-24T02:09:44.996Z",
    "is_admin": true,
    "date_added": "2013-09-23",
    "password": "",
    "email": "name@sample.com"
}
}
]

我认为问题可能与密码保存和返回的方式有关,因为无论我做什么,都会收到“请输入员工帐户的正确电子邮件和密码。请注意,两个字段均区分大小写。”的消息。我在那里设置的密码是“sample”。我尝试删除所有与哈希pw和清理相关的代码,但实际上仍在用户表中返回哈希值。
我希望我做错了一些明显的事情,提前感谢任何花时间查看这个问题的人。
3个回答

15

代码没问题,问题是你只使用了RemoteUserBackend而没有使用默认的后端:

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.RemoteUserBackend',
)
我从未亲自使用过,但是根据文档,很明显它只会在您的请求中检查REMOTE_USER标头,因此使您的密码登录尝试无关紧要。
如果您想拥有两者可用,可以将默认的ModelBackend添加为备选项:
AUTHENTICATION_BACKENDS = (
        'django.contrib.auth.backends.RemoteUserBackend',
        'django.contrib.auth.backends.ModelBackend',
)

或者完全摆脱RemoteUserBackend,让您的应用程序以默认方式进行身份验证。

希望这可以帮助到您。


感谢您抽出时间查看,不幸的是我仍然遇到同样的问题。我删除了AUTHENTICATION_BACKEND行以及与RemoteUser相关的任何内容,但仍无法登录。 - berserkia
@berserkia,你是否也将'django.contrib.auth.backends.ModelBackend'添加到了你的AUTHENTICATION_BACKENDS中?你能否更新你的question以展示你当前的settings.py设置? - kirbuchi

6
也许你可以尝试在 create_superuser 中设置。
user.is_active = True

1

确保您的超级用户与您创建的某个配置文件相关联,可以通过手动将其插入到数据库中来实现。

注意


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接