无法覆盖 AWS 中的 Django 身份验证模板

Cannot overwrite Django authentication templates in AWS

我开发了一个 Django 应用程序,我一直在使用 django-authtools 模块来使用电子邮件登录。它在我的笔记本电脑上运行良好,但当我尝试使用 Beanstalk 在 AWS 的生产环境中部署它时,Django 似乎无法识别身份验证模块的覆盖,并强制重定向到 django 内置身份验证模块。其他一切似乎都工作正常(从部署和应用程序的角度来看)。 它导致 500 错误:

xxx.xxx.xxx.xxx (-) - - [04/Jul/2017:19:07:54 +1000] "GET /accounts/login/ HTTP/1.1" 500 7807 "http://<removed>.ap-southeast-2.elasticbeanstalk.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"

    Internal Server Error: /accounts/login/
    Traceback (most recent call last):
      File "/opt/python/run/venv/lib/python3.4/site-packages/django/core/handlers/exception.py", line 41, in inner
        response = get_response(request)
      File "/opt/python/run/venv/lib/python3.4/site-packages/django/core/handlers/base.py", line 217, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "/opt/python/run/venv/lib/python3.4/site-packages/django/core/handlers/base.py", line 215, in _get_response
        response = response.render()
      File "/opt/python/run/venv/lib/python3.4/site-packages/django/template/response.py", line 107, in render
        self.content = self.rendered_content
      File "/opt/python/run/venv/lib/python3.4/site-packages/django/template/response.py", line 82, in rendered_content
        template = self.resolve_template(self.template_name)
      File "/opt/python/run/venv/lib/python3.4/site-packages/django/template/response.py", line 64, in resolve_template
        return select_template(template, using=self.using)
      File "/opt/python/run/venv/lib/python3.4/site-packages/django/template/loader.py", line 53, in select_template
        raise TemplateDoesNotExist(', '.join(template_name_list), chain=chain)
    django.template.exceptions.TemplateDoesNotExist: registration/login.html

同样,这在我的笔记本电脑上运行良好,但在 AWS 服务器上运行不正常。我找不到两者之间的任何区别,它们是 运行 相同版本的 django 和 django-authools:

$ pip freeze

[...]
Django==1.11.2
django-authtools==1.5.0
django-extensions==1.7.6
django-phonenumber-field==1.3.0
django-qsstats-magic==0.7.2
django-simple-captcha==0.5.5
django-storages==1.6.1
[...]

唯一的区别似乎是 python 的版本,在 AWS 上是 3.4.3,在我的笔记本电脑上是 3.5.2。

在服务器上,我的 settings.py 文件与笔记本电脑上的相同:

myproject/settings.py:

INSTALLED_APPS = [
    'myapp.apps.MyappConfig',
    'authtools',
    'captcha',
    'storages',
    'phonenumber_field',
    'django_extensions',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

AUTH_USER_MODEL = "authtools.User"

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },

}, ]

myapp/urls.py:

from authtools import urls
[...]
    url(r'^accounts/', include('authtools.urls')),
[...]

authtools/url.py:

from django.conf.urls import url
from authtools import views as authools_views


urlpatterns = [
    url(r'^login/$', authools_views.LoginView.as_view(), name='login'),
    url(r'^logout/$', authools_views.LogoutView.as_view(), {'next_page': '/accounts/login'}, name='logout'),
    url(r'^password_change/$', authools_views.PasswordChangeView.as_view(), name='password_change'),
    url(r'^password_change/done/$', authools_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
    url(r'^password_reset/$', authools_views.PasswordResetView.as_view(), name='password_reset'),
    url(r'^password_reset/done/$', authools_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
    url(r'^reset/done/$', authools_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
    url(r'^reset/(?P<uidb36>[0-9A-Za-z]{1,13})-(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
        authools_views.PasswordResetConfirmView.as_view()),
    url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
        authools_views.PasswordResetConfirmView.as_view(),
        name='password_reset_confirm'),
]

我也试过直接在url语句中传递模板(LoginView.as_view(template_name='myapp/login.html'))但结果相同

authtools/view.py 的摘录:

class LoginView(AuthDecoratorsMixin, WithCurrentSiteMixin, WithNextUrlMixin, FormView):
    print('ENTERING LOGIN VIEW')
    form_class = AuthenticationForm
    template_name = 'myapp/login.html'
    allow_authenticated = True
    success_url = resolve_url_lazy(settings.LOGIN_REDIRECT_URL)

    # BBB: This is deprecated (See LoginView.get_allow_authenticated)
    disallow_authenticated = None

错误 "registration/login.html" 中显示的模板是内置模板,而不是 authtools 模块提供的应该覆盖它的模板。 此外,当导航到我网站的 /admin/ 时,我可以使用我的超级用户正确登录,当返回该网站时,我会被检测为已通过身份验证。注销操作虽然将我重定向到默认注销页面,但没有使用 authtools 模块中提供的自定义模板(同样的行为)。

如果有人有解决方案或任何关于在哪里调查的想法,我们将不胜感激!

谢谢!

我正在添加我的 beantalk 配置文件以防万一,尽管我不认为这是与 beantalk 本身相关的问题。

.ebextensions# cat 001_set_env.config 
option_settings:
  "aws:elasticbeanstalk:application:environment":
    PYTHONPATH: /opt/python/current/app/myapp:/opt/python/current/app/authtools:$PYTHONPATH
  "aws:elasticbeanstalk:container:python":
    WSGIPath: "myproject/wsgi.py"
.ebextensions# cat 002_deploy.config 
commands:
  01_update_pip:
    command: "/opt/python/run/venv/bin/pip install --upgrade pip"
  02_set_time_zone:
    command: ln -f -s /usr/share/zoneinfo/Australia/Sydney /etc/localtime

container_commands:
  01_makemigration:
    command: "source /opt/python/run/venv/bin/activate && python manage.py makemigrations --noinput"
    leader_only: true
  02_migrate:
    command: "source /opt/python/run/venv/bin/activate && python manage.py migrate --noinput"
    leader_only: true
  03_initialize_db:
    command: "source /opt/python/run/venv/bin/activate && python manage.py initializedb"
    leader_only: true
  04_create_superuser:
    command: "source /opt/python/run/venv/bin/activate && python manage.py createsu"
    leader_only: true

我建议您停止编辑 authtools 中的代码。不清楚你是怎么做的,因为错误显示缺少的模板是 registration/login.html,它现在正在生产中工作。

如果您将模板从 myapp/templates/myapp/login.html 重命名为 myapp/templates/registration/login.html,应用程序目录加载程序应该会找到您的模板。

最后,顺便说一下,您的 DIRS 设置看起来不正确。

'DIRS': ['templates'],

如果要包含 myproject/templates 目录,请将其更改为

'DIRS': [os.path.join(BASE_DIR, 'templates')]

对于那些感兴趣的人,我终于找到了这个问题的问题。我在 site_packages 和本地项目中都安装了 authools 模块。在我的本地笔记本电脑上,优先顺序似乎是首先查看我的本地 django 项目(我的模块具有正确的模板路径),而在 AWS 上,列出的 python 路径顺序 site_packages首先,因此查看 authtools 的未修改版本。 因此,我删除了安装在我的项目中的 authtools 版本,我现在使用安装在 site_packages 中的原始版本,同时直接在我的应用 urls.py 中覆盖 authools 模板名称。

感谢大家的帮助,让我走上正轨。