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

Posted

技术标签:

【中文标题】Django - 覆盖管理站点的登录表单【英文标题】:Django - Override admin site's login form 【发布时间】:2012-07-05 16:48:09 【问题描述】:

我目前正在尝试在登录管理站点时覆盖 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 Admin 登录路由,Django 喜欢提供它自己的表单此模板,因此只有 usernamepassword 字段呈现。有什么办法可以使这项工作,还是我最好将 HTML 字段“硬编码”到表单中?

【问题讨论】:

【参考方案1】:

你好 我找到了一个非常简单的解决方案。 您只需要修改项目的urls.py文件(注意,不是应用程序)

    在您的 PROJECT 文件夹中找到文件 urls.py。 将此行添加到导入部分from your_app_name import views 找到此行url(r'^admin/', include(admin.site.urls)) 在该行上方添加以下内容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)),
]

【讨论】:

【参考方案2】:

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

子类AdminSite,然后使用您的子类的实例而不是django.contrib.admin.site 在管理员、urls.py 等中注册您的模型。

一切尽在documentation。

【讨论】:

这几乎可以工作:我现在唯一的问题是重写这个类会导致 .autodiscover() 方法停止工作。删除它会从管理站点中删除我的所有模型。我不确定如何从不同应用程序中的 admin.py 模块显式导入管理模型,这可能吗(或者更好,我们可以为我的新子类 AdminSite 启用 autodiscover() 吗?)【参考方案3】:

urls.py 中的这段代码对我来说很好用(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 上也很适合我。 只是为了完成这个答案:如果您以某种方式更改表单的字段,您还需要覆盖 admin/login.html 模板,通常覆盖 % block content %【参考方案4】:

我知道这是一个旧线程,但我想添加一些它帮助我找到的东西,以防它可以帮助其他人。

我正在使用特殊的远程身份验证 (Shibboleth) 并覆盖管理员 login_form 是不够的。我有一个设置 cookie 并返回变量并重定向到远程身份验证提供程序等的视图。

所以我的做法是:

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

效果很好! 感谢@dgk

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

我重定向到一个唯一的登录网址(我使用的是 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),
]

【讨论】:

以上是关于Django - 覆盖管理站点的登录表单的主要内容,如果未能解决你的问题,请参考以下文章

django:我如何实际覆盖管理站点模板

为啥在 Django 管理员的 save() 覆盖中将站点添加到对象似乎不起作用?

有没有一种简单的方法可以完全自定义 Django 管理站点以显示不是字段的变量?

覆盖 django-allauth 表单域

为我的应用程序之外的单个模型覆盖 django 管理员更改表单?

如何使登录表单在 Django 的整个站点上可用