Django:在使用电子邮件登录字段替代用户名后,超级用户和普通用户无法登录管理和用户页面

4

我一直在寻找答案,但仍然找不到适合我的解决方案。

我是Django的新手。我正在编写一个Web应用程序,基本上是一个博客,在博客中,作者将拥有自己的网站,并在每篇文章下面有一个评论区。我希望在创建超级用户后,他会自动成为作者之一。用户名字段不是必需的,因为作者将通过他们的名字和姓氏进行识别。这就是为什么我需要他们只使用电子邮件登录的原因。

我使用的Django版本是2.0,尽可能多地使用CBV(类基视图)。

在使用户名无关紧要并仅在登录页面中使用电子邮件和密码之后,我无法同时登录以下两种情况:

- 作为在网站登录页面上注册的用户 - 作为通过控制台命令createsuperuser注册的管理员

以下是实际示例。

在删除整个数据库并在网页上注册常规用户和在终端中注册superuser后,它们将正确保存在数据库中。用户名字段为空。

id username email first_name last_name is_active is_staff is_superuser

---------- ---------- ------------------- ---------- ---------- ---------- ---------- ------------

1 johnsmith@gmail.com John Smith 1 0 0

2 mysu@gmail.com Mysuper Myuser 1 1 1

然而,我无法在网站上作为普通用户或在管理页面上作为超级用户登录。

对于某些人来说,问题是后端配置在设置中。我遵循了文档中写的内容,因此我的设置文件的部分如下:

settings.py

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog_app',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
    # to let the superuser login
    'django.contrib.auth.middleware.RemoteUserMiddleware',
]

# Custom superuser configuration

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.RemoteUserBackend',
]

我的其他文件是:

models.py

from django.db import models
from django.urls import reverse
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.utils.text import slugify

# Create your models here.
class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """
        Creates and saves a User with the given email and password.
        """
        if not email:
            raise ValueError('The given email must be set')

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

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)

class Author(AbstractUser):
    """ Author and User model """

    objects = UserManager()

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

    username = models.CharField(max_length=40, unique=False, default='')
    email = models.EmailField(unique=True, max_length=256, verbose_name='email')
    slug = models.SlugField(unique=True, editable=False)

    def __str__(self):
        return self.name()

    def save(self, *args, **kwargs):

        slug_name = self.name()
        slug_number = 0

        while True:
            if slug_number == 0:
                pass
            else:
                slug_name = self.name() + "-" + str(slug_number)
            slug_number += 1
            if not Author.objects.filter(slug=slugify(slug_name)).exists():
                break

        self.slug = slugify(slug_name)

        super(Author, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('blog_app:author_detail', kwargs={'slug':self.slug})

    def name(self):
        """ The function for displaying the name of the author and slugs """
        return self.first_name + ' ' + self.last_name

class Article(models.Model):
    """ Article model """

    date = models.DateTimeField(auto_now_add=True, editable=False)
    date_updated = models.DateTimeField(auto_now=True, editable=False)
    title = models.CharField(max_length=256, unique=True)
    text = models.CharField(max_length=1024)
    author = models.ForeignKey(Author, null=True, blank=False, on_delete=models.SET_NULL, related_name='articles')
    slug = models.SlugField(unique=True, editable=False)

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        """ Creates slugs. If slug repeats then adds the number in the i the end
         which has not exist before. Those numbers are in the order """

        slug_name = self.title
        slug_number = 0

        while True:
            if slug_number == 0:
                pass
            else:
                slug_name = self.title + "-" + str(slug_number)
            slug_number += 1
            if not Article.objects.filter(slug=slugify(slug_name)).exists():
                break

        self.slug = slugify(slug_name)

        super(Article, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('blog_app:detail', kwargs={'slug':self.slug})

    def updates_detected(self):
        """ Checks whether updates happened. Due to microseconds calculations, it
        is impossible to check it by a regular comparison. Therefore I give the
        article a 1-minute margin. The update, which happened earlier than 1 minute
        from the creation of an article is assumed not to be an update """
        from datetime import timedelta

        d_creation = self.date.replace(tzinfo = None)
        d_update = self.date_updated.replace(tzinfo = None)
        td = timedelta(seconds = 5)

        if abs(d_update - d_creation) < td:
            return False
        else:
            return True

class Comment(models.Model):
    """ Comment model """

    date = models.DateTimeField(auto_now_add=True, editable=False)
    text = models.CharField(max_length=256)
    author = models.CharField(max_length=64)
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comments', unique=True)

    def __str__(self):
        return self.date

admin.py

from django.contrib import admin
from blog_app.models import Article, Comment, Author

# Register your models here.

admin.site.register(Article)
admin.site.register(Author)
admin.site.register(Comment)

forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm
from blog_app.models import Author

class SignUpForm(UserCreationForm):
    class Meta:
        model = Author
        fields = ('first_name', 'last_name', 'email', 'password1', 'password2')

views.py

from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.views.generic import (TemplateView, ListView, DetailView, CreateView,
                                    UpdateView, DeleteView)
from django.contrib.auth.views import LoginView, LogoutView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from blog_app import models
from blog_app.forms import SignUpForm


# Create your views here.

# Main pages
class IndexView(ListView):
    model = models.Article
    ordering = ['-date']
    context_object_name = 'articles'
    template_name = "blog_app/index.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['injectme'] = 'BASIC INJECTION'
        return context

class AboutMeView(TemplateView):
    template_name = "blog_app/about_me.html"

# Article views

class ArticlePageView(DetailView):
    context_object_name = 'article_detail'
    model = models.Article
    template_name = 'blog_app/article_page.html'

class CreateArticleView(LoginRequiredMixin, CreateView):
    login_url = reverse_lazy("blog_app:login")
    model = models.Article
    fields = ('title', 'text')

    def form_valid(self, form):
        author = self.request.user
        form.instance.author = author
        return super(CreateArticleView, self).form_valid(form)

class UpdateArticleView(LoginRequiredMixin, UpdateView):
    login_url = reverse_lazy("blog_app:login")
    model = models.Article
    fields = ('title', 'text')

class ArticleDeleteView(LoginRequiredMixin, DeleteView):
    login_url = reverse_lazy("blog_app:login")
    model = models.Article
    success_url = reverse_lazy("blog_app:index")

# Author/user views

class AuthorPageView(DetailView):
    context_object_name = 'author_detail'
    model = models.Author
    template_name = 'blog_app/author_page.html'

class LoginAuthorView(LoginView):
    template_name = 'blog_app/login.html'
    success_url = reverse_lazy("blog_app:index")

class LogoutAuthorView(LogoutView):
    next_page = reverse_lazy("blog_app:index")

class CreateAuthorView(CreateView):
    model = models.Author
    form_class = SignUpForm

class UpdateAuthorView(LoginRequiredMixin, UpdateView):
    login_url = reverse_lazy("blog_app:login")
    model = models.Author
    fields = ['first_name']

class AuthorDeleteView(LoginRequiredMixin, DeleteView):
    login_url = reverse_lazy("blog_app:login")
    model = models.Author
    success_url = reverse_lazy("blog_app:index")

你知道我可能有什么问题吗?

你最终解决了这个问题吗? - Kenny Worden
你最终找到解决方案了吗? - Tamdim
1个回答

0

你是否已按照此处文档自定义用户模型的说明,在 settings.py 中使用 AUTH_USER_MODEL 设置注册了你的自定义用户模型?


谢谢您的回答! :) 是的,我已经注册了。它在设置中,代码是: - Jakub Siwiec
AUTH_USER_MODEL = 'blog_app.Author' 作者已在admin.py中注册。在您的回答后,我检查并尝试将UserAdmin作为site.register中的附加参数添加,就像文档中所做的那样 - 但仍然无法正常工作。 - Jakub Siwiec

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