Django - 覆盖管理站点的登录表单

18

我目前正在尝试覆盖Django 1.4中在管理员网站登录时使用的默认表单(我的网站使用额外的“令牌”字段,需要用户选择两种因素身份验证,并且对于网站工作人员是强制性的)。 Django的默认表单不支持我所需的功能。 目前,在我的 templates / 目录中有一个名为 templates / admin / login.html 的文件,它似乎正确地覆盖了使用的模板与我整个网站上使用的那个相同。 文件的内容只是如下:

# admin/login.html:
{% extends "login.html" %}

实际的登录表单如下:

# login.html:
{% load url from future %}<!DOCTYPE html>
<html>
    <head>
        <title>Please log in</title>
    </head>
    <body>
        <div id="loginform">
            <form method="post" action="{% url 'id.views.auth' %}">
                {% csrf_token %}
                <input type="hidden" name="next" value="{{ next }}" />
                {{ form.username.label_tag }}<br/>
                {{ form.username }}<br/>
                {{ form.password.label_tag }}<br/>
                {{ form.password }}<br/>
                {{ form.token.label_tag }}<br/>
                {{ form.token }}<br/>
                <input type="submit" value="Log In" />
           </form>
        </div>
    </body>
</html>
我的问题是,当我使用正常的登录URL访问提供的表单时,它运行得非常好,因为我提供了自己的AuthenticationForm作为要显示的表单,但是通过Django管理登录路由访问时,Django喜欢提供自己的表单给这个模板,因此只有usernamepassword字段被渲染。有没有办法使这个工作,或者我最好只是将HTML字段'硬编码'到表单中呢?
6个回答

22

Holá
我发现一个非常简单的解决方案。
您只需要修改项目的urls.py文件(请注意,不是应用程序的文件)

  1. 在您的项目文件夹中找到urls.py文件。
  2. 在导入部分添加此行代码
    from your_app_name import views
  3. 找到此行代码
    url(r'^admin/', include(admin.site.urls))
  4. 在该行之上添加以下内容
    url(r'^admin/login/', views.your_login_view),

这是一个示例

from django.conf.urls import include, url
from django.contrib import admin

from your_app import views

urlpatterns = [
    url(r'^your_app_start/', include('your_app.urls',namespace="your_app_name")),

    url(r'^admin/login/', views.your_app_login),
    url(r'^admin/', include(admin.site.urls)),
]

14

AdminSite 有一个 login_form 属性,可以用来覆盖使用的表单。

通过继承 AdminSite 并使用你的子类的实例来注册你的模型到管理员界面,包括在 urls.py 中等地方,而非使用 django.contrib.admin.site

详见 文档


1
这个几乎可以工作:我现在唯一遇到的问题是覆盖这个类会导致 .autodiscover() 方法停止工作。如果移除这个类,所有我的模型都将从管理站点中移除。我不确定如何明确地从不同应用程序的 admin.py 模块中导入管理模型,这是否可能(或者更好的方法是,我们能否为我的新子类化 AdminSite 启用 autodiscover()?) - TC Fox

13

这段代码在我的机器上运行良好(Django 版本为 1.5.1):

from django.contrib import admin
from my.forms import AuthenticationForm

admin.autodiscover()
admin.site.login_form = AuthenticationForm

在我的Django 1.6.1上也能良好运作。 - Rodrigo Deodoro
1
只是为了完善这个答案:如果您在某种程度上更改了表单的字段,您还需要覆盖admin/login.html模板,通常是覆盖{% block content %} - Caumons

2

我知道这是一个旧的帖子,但是我想添加一些东西来帮助我找到,以防其他人也需要。

我正在使用特殊的远程认证(Shibboleth),覆盖管理员登录表单是不够的。我有一个视图设置Cookie并返回变量,然后重定向到远程认证提供者等。

所以我做的方式是:

from my_app.views import user_login, user_logout
admin.autodiscover()
admin.site.login = user_login
admin.site.logout = user_logout

工作得很好!感谢 @dgk


1

我重定向到一个唯一的登录URL(我使用django 2.1和python 3.6 f-strings):

from apps import admin
from django.urls import path, include
from django.shortcuts import redirect

urlpatterns = [
    path(
        'admin/login/',
        lambda r: redirect(
            f"/login?{r.META['QUERY_STRING']}" if r.META['QUERY_STRING'] \
            else '/login'
        )
    ),
    path('admin/', admin.site.urls),
]

0

或许可以使用模板标签来获取您的自定义AuthenticationForm


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