【问题标题】:Adding link to django admin page添加到 django 管理页面的链接
【发布时间】:2012-04-10 01:01:16
【问题描述】:

我有一个使用 django 构建的应用程序的客户端。在每一页 他们的应用程序是指向其管理站点的链接。他们告诉我管理网站 完全由 django 生成,他们从未定制过 前。在管理页面的第一行它说:

Django 管理 欢迎,管理员。更改密码/登出

他们希望我在“Django”左侧添加指向该行的链接 管理”,这将使他们回到他们当时所在的页面 他们点击链接将他们带到管理站点。

所以我这里有两个问题:

  1. 如何覆盖该行以添加链接?看起来那个页面 由 contrib/admin/templates/admin/base.html 生成,我试过了 按照以下说明覆盖它 https://docs.djangoproject.com/en/1.2/ref/contrib/admin/#overriding-a..., 但无论我做什么似乎都没有效果。

  2. 如何获取他们来自的应用程序页面的链接?它是 不仅仅是返回一页,因为他们可以浏览所有 在单击“返回应用程序”之前,在管理站点的位置上 链接。

【问题讨论】:

    标签: python django django-admin


    【解决方案1】:

    有很多方法可以将上次访问的非管理员 url 存储在 request.session 中。例如,一个中间件:

    import re
    
    class LastSiteUrl(object):
        def is_admin_url(self, url):
            return re.search('^(http:\/\/.*){0,1}\/admin\/', url) is not None
    
        def process_request(self, request):
            if self.is_admin_url(request.path) and \
                not self.is_admin_url(request.META.get('HTTP_REFERER','')):
                request.session['last_site_url'] = request.META.get('HTTP_REFERER','')
    

    然后覆盖模板:

    1. 将最后一个非管理员 url 存储在 request.session 中,例如把上面的类放到yourproject/middleware.py,添加到settings.MIDDLEWARE_CLASSESmiddleware.LastSiteUrl

    2. 准备管理基础站点模板以进行覆盖,将django/contrib/admin/templates/admin/base_site.html复制到yourproject/templates/admin/base_site.html

    3. 链接到 request.session.last_site_url,例如在yourproject/templates/admin/base_site.html中,找到{% block branding %},在这个block的H1标签前,添加一个指向{{ request.session.last_site_url }}的HTML链接。

    应该是这样的:

    {% block branding %}
        {% if request.session.last_site_url %}
            <a href="{{ request.session.last_site_url }}">back to site</a>
        {% endif %}
        <h1 id="site-name">{% trans 'Django administration' %}</h1>
    {% endblock %}
    

    【讨论】:

    • 不客气。很高兴看到改进的答案并从中学习 =)
    • 感谢中间件上的指针。我会尝试一下。但至于覆盖 base_site,我无法让它工作。我之前尝试过您在第 2 步中所说的内容,但我对 base_site 的更改没有被采纳。有什么我必须做的事情导致这种情况发生吗? (我对 django 很陌生。)我将 base_site 复制到我的项目的模板/管理目录中。我还将它添加到 TEMPLATE_DIRS (之前没有任何内容)。在 urlpatterns 我有: (r'^admin/', include(admin.site.urls)) - 需要改变吗?
    • @LarryMartell 你的 TEMPLATE_DIRS 现在是什么样子的?
    • 我发现了我的问题 - 我将带有 base_site.html 的目录的完整路径放在 TEMPLATE_DIRS 中(例如 SRC_ROOT/templates/admin/)。当我删除最后一个目录并将其更改为 SRC_ROOT/templates/ 时,它会拾取我的文件。
    • @jpic 这似乎不适用于使用 wsgi 在非根 URL 上运行 django。虽然它适用于 root 安装...
    【解决方案2】:

    简单的方法:

    如果模型具有 get_absolute_url 函数,则管理员“更改”页面会在页面右上角包含一个“现场查看”按钮。因此,请确保您的模型包含 get_absolute_url:

        def get_absolute_url(self):
            return '/myapp/%s' %self.slug #this should reflect your url-structure.
    

    “现场查看”按钮不在“添加”页面上,因为需要先创建对象才能访问它。告诉您的客户在创建新对象时不要点击“保存”而是“保存并继续编辑”,然后点击“现场查看”。

    现在还可以通过覆盖 base_site.html 轻松跳转到当前模型条目的网站表示。这里我们检查当前模型是否包含absolute_url。如果您不在 change_page 上,则不会有 absolute_url。在这种情况下,链接会将您带到主页。

    templates/admin/base_site.html

    {% extends "admin/base.html" %}
    {% load i18n %}
    
    {% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}
    
    {% block branding %}
    <h1 id="site-name">{% if has_absolute_url %}<a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% else %}<a href="http://{{ site.domain }}">{% endif %}{{ site.domain }}</a>    
    
     Sitebeheer{#{% trans 'Django administration' %}#}</h1>
    {% endblock %}
    
    {% block nav-global %}{% endblock %}
    

    完成!

    以下解决方案也可以回答您的问题,但方式不同。这将在管理员“添加”和“更改”页面上的“保存并继续”和“保存”按钮旁边添加一个“保存并在网站上查看”按钮:

    1. 确保您的模型包含 get_absolute_url 函数。
    2. 覆盖管理员响应以重定向到此 absolute_url。
    3. 覆盖 change_form.html 以添加“保存并在网站上查看”按钮。

    编辑 myproject/myapp/models.py

    class MyModel(models.Model):
        title = models.CharField("titel", max_length=200)
        slug = models.SlugField(unique=True)
    
        def __unicode__(self):
            return self.title
    
        def get_absolute_url(self):
            return '/myapp/%s' %self.slug
    

    编辑 myproject/myapp/admin.py

    from models import MyModel
    
    class MyModelAdmin(admin.ModelAdmin):
        ...
    
        def response_change(self, request, obj):
            """
            Determines the HttpResponse for the change_view stage.
            """
            if request.POST.has_key("_viewsite"):
                msg = (_('The %(name)s "%(obj)s" was changed successfully.') %
                       {'name': force_unicode(obj._meta.verbose_name),
                        'obj': force_unicode(obj)})
                return HttpResponseRedirect(obj.get_absolute_url())
            return super(MyModel, self).response_change(request, obj)
    
    admin.site.register(MyModel, MyModelAdmin)
    

    创建一个新文件 myproject/templates/admin/myapp/change_form.html:

    {% extends "admin/change_form.html" %}
    {% load i18n %}
    {% block content %}
    {{ block.super }}
    <script type="text/javascript">//<![CDATA[
        (function($){
            $('<input type="submit" value="Save and view on site" name="_viewsite" />')
            .prependTo('div.submit-row');
        })(django.jQuery);
    //]]></script>
    {% endblock %}
    

    模板将覆盖 myapp 中每个模型的 change_form。在您的情况下,这可能是不可取的,因为并非所有模型在网站中都有表示(没有也不需要 get_absolute_url)。我认为您也可以将模板放在 myproject/templates/admin/myapp/MyModel/change_form.html 中,以仅覆盖 MyModel 的模板,并使用默认模板将其他模型留在 myapp 中。我从未对单个模型使用 change_form 模板。你会告诉我它是否有效吗?

    非常感谢您:http://djangosnippets.org/snippets/2005/

    这是否回答了您的问题?希望对你有帮助。

    【讨论】:

      最近更新 更多