在使用自定义用户模型创建超级用户后无法登录django admin

时间:2013-09-24 02:15:26

标签: django django-models django-admin django-custom-manager

我一直在尝试使用成功创建的超级用户登录django管理面板几个小时,但无法获得正确的用户名/ pw组合。

我希望用户只使用他们的电子邮件作为用户名。我也尽力在Django docs here中复制这个例子。我删除了迁移,sycndb,除了登录管理面板外,一切正常。

相关代码: 来自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"
}
}
]

我认为这必须与保存和退回密码的方式有关,因为无论我做什么,我都会得到“请为员工帐户输入正确的电子邮件和密码。请注意,这两个字段可能是区分大小写。”信息。我在那里设置的密码是“样本”。我已经尝试删除所有与哈希pw相关的代码并清理它,但实际上仍然在用户表中返回一个哈希。

我希望我做的事情显然是错误的,感谢任何花时间仔细研究整个问题的人。

3 个答案:

答案 0 :(得分:10)

代码很好。问题是你是专门使用RemoteUserBackend而不是default backend

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

我自己从未使用过它,但是from the docs很明显,它只会在您的请求中检查REMOTE_USER标头,从而使您的密码登录尝试无关紧要。

如果您不想同时使用,可以添加默认的ModelBackend作为后备:

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

或完全摆脱RemoteUserBackend并让您的应用验证默认方式。

希望这有帮助。

答案 1 :(得分:3)

也许你也可以尝试在 create_superuser 中设置

user.is_active = True

答案 2 :(得分:1)

确保超级用户已与您创建的配置文件之一相关联,也许是通过手动在数据库简介中输入该超级用户来实现的。

保重

相关问题