无法使用自定义用户和Mezzanine / South登录Django Admin

时间:2014-10-18 01:26:40

标签: python django admin django-south mezzanine

我有一个像这样的自定义用户的django应用程序:

import ...

logger = logging.getLogger(__name__)


# # Person (representation of people)


class AbstractPerson(models.Model):
    """
    ABSTRACT model representing basic information about a person on the platform,
    be it a user or a person used in acts he's generating.
    """

    MALE = 'M'
    FEMALE = 'F'
    GIRL = 'G'
    FRENCH_TITLES = (
        (MALE, 'M.'),
        (FEMALE, 'Mme'),
        (GIRL, 'Mlle'),
    )

    date_created = models.DateTimeField(_('date created'),
                                        default=timezone.now,
                                        db_index=True)

    title = models.CharField(u'Civilité', max_length=1,
                             choices=FRENCH_TITLES,
                             blank=True)
    first_name = models.CharField(u'Prénom', max_length=500, blank=True)
    last_name = models.CharField(u'Nom', max_length=500, blank=True,
                                 db_index=True)
    phone = models.CharField(u'Téléphone', max_length=10, blank=True)
    address_1 = models.CharField(u'Adresse', max_length=200, blank=True)
    address_2 = models.CharField(u"Complément d'adresse", max_length=200,
                                 blank=True, null=True)
    zipcode = models.CharField(u'Code Postal', max_length=10, blank=True)
    city = models.CharField(u'Ville', max_length=50, blank=True)


    class Meta:
        abstract = True


# # Auth

class UserManager(BaseUserManager):
    """Replacement for django auth's UserManager"""

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

        now = timezone.now()

        user = self.model(email=email,
                          is_staff=False, is_active=True, is_superuser=False,
                          last_login=now, date_created=now, **extra_fields)

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password, **extra_fields):
        u = self.create_user(email, password=password, **extra_fields)
        u.is_staff = True
        u.is_active = True
        u.is_superuser = True
        u.save(using=self._db)
        return u


class User(AbstractPerson, AbstractBaseUser, PermissionsMixin):
    """
    Replacement for django.contrib.auth's User.
    Gets basic Person information injected from AbstractPerson
    """

    # Regular fields
    email = models.EmailField(_('email address'), max_length=255,
                              unique=True, db_index=True)
    is_staff = models.BooleanField(_('staff status'), default=False,
                                   help_text=_('Designates whether the user '
                                               'can log into this admin site.'))
    is_active = models.BooleanField(_('active'), default=True,
                                    help_text=_('Designates whether the user '
                                                'should be treated as active. '
                                                'Unselect this instead of '
                                                'deleting accounts.'))

    # Compatibility with Mezzanine accounts app
    username = models.EmailField(_('username (copy of email address)'),
                                 max_length=255,
                                 unique=True, db_index=True)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []  # Nothing required apart from email


    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')
    abstract = False

    def save(self, *args, **kwargs):
        self.username = self.email
        try: kwargs.pop('username')
        except KeyError: pass
        super(User, self).save(*args, **kwargs)

然后我的设置是:

# Custom user model
AUTH_USER_MODEL = 'useraccount.User'

INSTALLED_APPS = (
    'grappelli',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.comments',
    'django.contrib.contenttypes',
    "django.contrib.redirects",
    'django.contrib.sessions',
    "django.contrib.sites",
    "django.contrib.sitemaps",
    'django.contrib.staticfiles',
    "storages",          # django-storages backend
    ## Custom user model and such
    'useraccount',
    ## Mezzanine
    "mezzanine.boot",
    "mezzanine.conf",
    "mezzanine.core",
    "mezzanine.generic",
    #"mezzanine.blog",
    "mezzanine.forms",
    "mezzanine.pages",
    #"mezzanine.galleries",
    #"mezzanine.twitter",
    #"mezzanine.accounts",
    #"mezzanine.mobile",
    'south',
)

MIDDLEWARE_CLASSES = (
    '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',
    "mezzanine.core.request.CurrentRequestMiddleware",
    "mezzanine.core.middleware.RedirectFallbackMiddleware",
    "mezzanine.core.middleware.TemplateForDeviceMiddleware",
    "mezzanine.core.middleware.TemplateForHostMiddleware",
    "mezzanine.core.middleware.AdminLoginInterfaceSelectorMiddleware",
    "mezzanine.core.middleware.SitePermissionMiddleware",
    # Uncomment the following if using any of the SSL settings:
    #"mezzanine.core.middleware.SSLRedirectMiddleware",
    "mezzanine.pages.middleware.PageMiddleware",
    "mezzanine.core.middleware.FetchFromCacheMiddleware",
)

所以现在,我已经同步了db并创建了一个超级用户。在shell中,一切看起来都很好:

In [1]: from useraccount.models import User

In [2]: from django.contrib.auth import authenticate

In [3]: authenticate(username='john', password='secret')
Out[3]: <User: john>

In [4]: u = User.objects.all()[0]

In [5]: u.is_active
Out[5]: True

In [6]: u.is_staff
Out[6]: True

In [7]: u.is_superuser
Out[7]: True

有了这一切,无法连接到管理员......管理员不说:     Please enter the correct email address and password for a staff account. Note that both fields may be case-sensitive.

但:     Please correct the error below.

有什么想法吗?

修改

抱歉,我没有预先确定我使用MezzanineBackend对用户进行身份验证:

AUTHENTICATION_BACKENDS = ("mezzanine.core.auth_backends.MezzanineBackend",)

代码是这样的:

class MezzanineBackend(ModelBackend):

def authenticate(self, **kwargs):
    if kwargs:
        username = kwargs.pop("username", None)
        if username:
            username_or_email = Q(username=username) | Q(email=username)
            password = kwargs.pop("password", None)
            try:
                user = User.objects.get(username_or_email, **kwargs)
            except User.DoesNotExist:
                pass
            else:
                if user.check_password(password):
                    return user
        else:
            if 'uidb36' not in kwargs:
                return
            kwargs["id"] = base36_to_int(kwargs.pop("uidb36"))
            token = kwargs.pop("token")
            try:
                user = User.objects.get(**kwargs)
            except User.DoesNotExist:
                pass
            else:
                if default_token_generator.check_token(user, token):
                    return user

也许问题是没有get_user方法,所以我会尝试这个并且如果它不起作用则返回

EDIT2

添加了get_user方法没有变化......有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我认为您的问题来自这样一个事实,即您的新用户模型虽然已注册到settings.py,但没有关联的身份验证后端。因此无法在您的应用中对其进行身份验证。

遵循本教程:https://docs.djangoproject.com/en/dev/topics/auth/customizing/您应该有一个如下所示的文件:

from django.conf import settings
from django.contrib.auth.models import User, check_password

class SettingsBackend(object):
"""
Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.

Use the login name, and a hash of the password. For example:

ADMIN_LOGIN = 'admin'
ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'
"""

def authenticate(self, username=None, password=None):
    login_valid = (settings.ADMIN_LOGIN == username)
    pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
    if login_valid and pwd_valid:
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            # Create a new user. Note that we can set password
            # to anything, because it won't be checked; the password
            # from settings.py will.
            user = User(username=username, password='get from settings.py')
            user.is_staff = True
            user.is_superuser = True
            user.save()
        return user
    return None

def get_user(self, user_id):
    try:
        return User.objects.get(pk=user_id)
    except User.DoesNotExist:
        return None

settings.py

的方式注册
AUTHENTICATION_BACKENDS ('mybackend',)

您可能还需要覆盖admin.py的{​​{1}}文件 然后你可以注册

django.contrib.auth.admin.UserAdmin

能够在管理控制台中看到它。

PS is_staff和is_superuser应该是callables,而不是布尔值

答案 1 :(得分:0)

好吧,所以django-grappelli搞砸了我的管理员。我为grappelli_safe更改了它,现在一切都很好:)。

相关问题