升级到 2.1 后 Django 管理员无法登录

Posted

技术标签:

【中文标题】升级到 2.1 后 Django 管理员无法登录【英文标题】:Django admin failing to login after upgrade to 2.1 【发布时间】:2019-05-08 17:57:47 【问题描述】:

将旧的 Django 1.8 升级到 2.1 后,当我尝试登录我的管理站点时,我收到 404 消息:

Using the URLconf defined in <mysite>.urls, Django tried these URL patterns, in this order:
[...]
The current path, login/, didn't match any of these.

我猜这是真的,因为它应该在 __admin/login 上,就像在我的 urls.py 中一样:

urlpatterns = [
    ...
    path(r'__admin/', admin.site.urls),
    ...
]

但是:

GET请求/__admin/login按预期返回登录页面 该问题仅发生在生产环境中(VPS 上的乘客 WSGI),而不是本地主机上 通过manage.py shelldjango.contrib.auth.authenticate() 手动登录用户工作正常 不幸的是,升级与 VPS 机器的迁移同时发生,因此数据库也可能存在问题。

Python 版本(在 VPS 上):3.6.7Django 版本(在 VPS 上):2.1.3(也尝试使用 2.1.4)

编辑 1

我已注释掉所有其他 urls,因此现在唯一可用的 URL 是 __admin。现在,当我登录时出现此错误:

Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:

     1. __admin/

The current path, login/, didn't match any of these.

看起来 django 正在寻找 login/ 而不是 __admin/login。这可能吗?是什么原因造成的?

编辑 2 添加了设置文件。

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
from django.contrib import messages

PROJ_SHORTNAME = '<removed>'
PROJ_NAME      = '<removed>'

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = <removed>

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',        
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',
    'bootstrap3',
    'mysite',
    'blog',
    'envelope',         # required for contact page
    'crispy_forms',     # required for contact page
    'honeypot',         # required for contact page
    'braces',           # required for contact page
    'disqus',
    'markdownx',
)

MIDDLEWARE = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = '<removed>.urls'

TEMPLATES = [
    
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': 
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.template.context_processors.media',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'mysite.context_preprocessors.proj_name',
            ],
        ,
    ,
]

WSGI_APPLICATION = '<removed>.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

DATABASES = 
    'default': 
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': PROJ_SHORTNAME,
        'HOST': 'localhost',
        'USER': '<removed>',
        'PASSWORD': '<removed>',
    



# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-gb'
TIME_ZONE = 'Europe/London'
USE_I18N = True
USE_L10N = True
USE_TZ = True

# Static files (CSS, javascript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL  = '/media/'

## Markdown 
MARKDOWN_EXTENSIONS = ['extra', 'codehilite']

MESSAGE_TAGS = 
    messages.DEBUG: 'debug',
    messages.INFO: 'info',
    messages.SUCCESS: 'success',
    messages.WARNING: 'warning',
    messages.ERROR: 'danger' # 'error' by default


## contact (envelope)
HONEYPOT_FIELD_NAME = 'email2'
CRISPY_TEMPLATE_PACK = 'bootstrap3'
ENVELOPE_USE_html_EMAIL = False
ENVELOPE_SUBJECT_INTRO = "[<removed>] "
ENVELOPE_EMAIL_RECIPIENTS = ['<removed>']

## disqus
DISQUS_API_KEY = '<removed>'
DISQUS_WEBSITE_SHORTNAME = '<removed>'

## django sites
SITE_ID = 1

BOOTSTRAP3 = 

    # The URL to the jQuery JavaScript file
    'jquery_url': STATIC_URL+'mysite/js/jquery.min.js',

    # The Bootstrap base URL
    'base_url': STATIC_URL+'mysite/',

    # The complete URL to the Bootstrap CSS file (None means derive it from base_url)
    "css_url": 
        "url": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css",
        "integrity": "sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u",
        "crossorigin": "anonymous",
    ,

    # The complete URL to the Bootstrap CSS file (None means no theme)
    'theme_url': None,

    # The complete URL to the Bootstrap JavaScript file (None means derive it from base_url)
    "javascript_url": 
        "url": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js",
        "integrity": "sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa",
        "crossorigin": "anonymous",
    ,

    # Put JavaScript in the HEAD section of the HTML document (only relevant if you use bootstrap3.html)
    'javascript_in_head': False,

    # Include jQuery with Bootstrap JavaScript (affects django-bootstrap3 template tags)
    'include_jquery': False,

    # Label class to use in horizontal forms
    'horizontal_label_class': 'col-md-3',

    # Field class to use in horizontal forms
    'horizontal_field_class': 'col-md-9',

    # Set HTML required attribute on required fields
    'set_required': True,

    # Set HTML disabled attribute on disabled fields
    'set_disabled': False,

    # Set placeholder attributes to label if no placeholder is provided
    'set_placeholder': True,

    # Class to indicate required (better to set this in your Django form)
    'required_css_class': '',

    # Class to indicate error (better to set this in your Django form)
    'error_css_class': 'has-error',

    # Class to indicate success, meaning the field has valid input (better to set this in your Django form)
    'success_css_class': 'has-success',

    # Renderers (only set these if you have studied the source and understand the inner workings)
    'formset_renderers':
        'default': 'bootstrap3.renderers.FormsetRenderer',
    ,
    'form_renderers': 
        'default': 'bootstrap3.renderers.FormRenderer',
    ,
    'field_renderers': 
        'default': 'bootstrap3.renderers.FieldRenderer',
        'inline': 'bootstrap3.renderers.InlineFieldRenderer',
    ,



try:
    from <removed>.local_settings import *
except ImportError:
    pass

还有local_settings.py:

import os
DEBUG = False

STATIC_ROOT = '/home/<removed>/public_html/<removed>/static/'

DATABASES = 
    'default': 
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': '<removed>',
        'HOST': 'localhost',
        'USER': '<removed>',
        'PASSWORD': '<removed>',
    


FROM_EMAIL = '<removed>'

BOOTSTRAP3 = 

    # The URL to the jQuery JavaScript file
    'jquery_url': '//code.jquery.com/jquery.min.js',


ALLOWED_HOSTS = [
    '<removed>', # Allow domain and subdomains
    '.<removed>.', # Also allow FQDN and subdomains
    '<removed>', # Also allow FQDN and subdomains
]

LOGIN_URL="/__admin/login/"

LOGGING = 
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': 
        'file': 
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': os.path.expanduser('~/logs/django/debug.log'),
        ,
    ,
    'loggers': 
        'django': 
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        ,
    ,

【问题讨论】:

您是否检查过您没有使用某种 prod_urls.py 文件或类似文件覆盖某些 ULR 设置? 不,我没有prod_urls.py 您能否分享有关您的项目的更多信息,例如 Python 版本以及本地和生产环境的设置? @PaoloMelchiorre 谢谢,我在问题中添加了 python 版本(3.6.7)和 Django 版本(2.1.3),以及settings.pylocal_settings.py 我阅读了您的设置,如果您可以通过 urls.py 可能会有所帮助 【参考方案1】:

测试

我试图重现您创建空 Django 2.1 项目的错误,然后按照您的报告修改了项目文件:

urls.py

from django.contrib import admin
from django.urls import path
urlpatterns = [path(r'__admin/', admin.site.urls)]

local_settings.py

DEBUG = False
ALLOWED_HOSTS = ['*']
LOGIN_URL = "/__admin/login/"

settings.py

import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = 'secret-key'
DEBUG = True
ALLOWED_HOSTS = []
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',
)
MIDDLEWARE = (
    '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',
    'django.middleware.security.SecurityMiddleware',
)
ROOT_URLCONF = 'so.urls'
TEMPLATES = [
    
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': 
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.template.context_processors.media',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        ,
    ,
]
WSGI_APPLICATION = 'so.wsgi.application'
DATABASES = 
    'default': 
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    

LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
SITE_ID = 1
try:
    from so.local_settings import *  # noqa
except ImportError:
    pass

我无法重现您的错误,我认为您的代码没问题。

建议

我认为您在 VPS 上出错的主要动机是在 VPS 上。

您的 VPS 上是否有过时的 .pyc 或 .pyo 文件?

如果是这样,请尝试删除它们,然后重新启动 VPS。

如果您解决了错误,为了防止以后出现此问题,您应该在启动 VPS 之前删除 .pyc 或 .pyo 文件。

【讨论】:

谢谢,好建议。我刚刚删除了所有 *.pyc 和 *.pyo 文件并重新启动,但不幸的是没有任何改变。 但是,如果他的问题只发生在生产环境中,那么您的 VPS 就会有所不同。我认为您需要在本地和生产环境之间搜索不同的设置。【参考方案2】:

看来这个问题与settings.py有关。我遇到了同样的问题并更改了我的 settings.py

    MIDDLEWARE_CLASSES 重命名为 MIDDLEWARE

    注释了对“django.contrib.auth.middleware.SessionAuthenticationMiddleware”的引用

问题消失了

【讨论】:

我的settings.py 已经有MIDDLEWARE 而不是MIDDLEWARE_CLASSES 并且没有引用django.contrib.auth.middleware.SessionAuthenticationMiddleware。您能否发布其余的MIDDLEWARE 列表以供参考?谢谢【参考方案3】:

尝试在您的settings.py 中设置LOGIN_URL

LOGIN_URL = '__admin/login'

https://docs.djangoproject.com/en/2.1/ref/settings/#login-url

默认:'/accounts/login/'

为了登录而重定向请求的 URL,尤其是在使用 login_required() 装饰器时。

【讨论】:

试过了,不管有没有。注意 a) 登录页面的 GET 请求正常工作,并在/__admin/login 处显示登录表单; b)登录本身在本地主机上工作。【参考方案4】:

我也只需要进行增量升级,从 Django 1.8 升级到 2.2。

我按照 bir singh 之前的建议做了(但是太长了,无法作为评论发布)。我希望这对某人有所帮助。

我找到了 Django 设置文件 注释掉MIDDLEWARE_CLASSES 以供参考 添加了MIDDLEWARE 默认部分

# Django upgrade 1.11 to 2.x
# MIDDLEWARE_CLASSES = (
#     'django.contrib.sessions.middleware.SessionMiddleware',
#     'django.middleware.common.CommonMiddleware',
#     'django.middleware.csrf.CsrfViewMiddleware',
#     'django.contrib.auth.middleware.AuthenticationMiddleware',
#     'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
#     'django.contrib.messages.middleware.MessageMiddleware',
#     'django.middleware.clickjacking.XFrameOptionsMiddleware',
#     'django.middleware.security.SecurityMiddleware',
# )

MIDDLEWARE = [
    # The following is the list of default middleware in new Django projects.
    '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',
]

启动runserver 并检查网站功能(一切正常

以前我会在升级后收到此错误:

django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:

ERRORS:
?: (admin.E408) 'django.contrib.auth.middleware.AuthenticationMiddleware' must be in MIDDLEWARE in order to use the admin application.
?: (admin.E409) 'django.contrib.messages.middleware.MessageMiddleware' must be in MIDDLEWARE in order to use the admin application.

【讨论】:

【参考方案5】:

我正在使用 python 3.8v 和 django 2.2。

我也有这个问题。

使用这个 url(r'^$admin/', admin.site.urls) settings.py 我无法访问登录表单。

但是,尝试这个path('admin/', admin.site.urls) 我能够访问并修复它。

【讨论】:

以上是关于升级到 2.1 后 Django 管理员无法登录的主要内容,如果未能解决你的问题,请参考以下文章

Django:创建电子邮件登录字段而不是用户名后,超级用户和用户无法登录到管理员和用户页面

创建超级用户后无法登录 django 管理员帐户

Django 中的异常错误。创建超级用户后无法登录管理员

无法使用有效的用户名和密码登录 django 管理页面

ImportError:升级到 Django 4.0 后无法从“django.conf.urls”导入名称“url”

从 1.8 升级到 2.2.4 后,Django 无法创建用于单元测试的表