如何在 Django 的自定义 404 错误模板中显示传递给 Http404 的消息?

Posted

技术标签:

【中文标题】如何在 Django 的自定义 404 错误模板中显示传递给 Http404 的消息?【英文标题】:How to display the message passed to Http404 in a custom 404 Error template in Django? 【发布时间】:2010-12-09 22:06:30 【问题描述】:

我有一个正在 django 中工作的项目。在很多情况下,我:

raise Http404("this is an error")

它为我创建了一个漂亮的 404 页面,上面写着错误消息“这是一个错误”。

我现在想创建一个自定义错误页面并让它仍然显示消息,但我不知道如何。

我确定这只是我需要添加到自定义 404 模板中的模板变量,但我找不到任何文档。

【问题讨论】:

您是否找到了将“这是一个错误”消息输入自定义 404 处理程序的方法? @Alasdair,nbv4,我真的很感激你的帮助。 @marianobianchi 我错误地说可以使用自定义 404 处理程序来实现这一点,但实际上不可能。有一个pull request 需要更改,但被拒绝了。想了想,我同意这个决定。我认为最好使用 Euribates 建议的消息框架,或者呈现自定义模板并返回状态 404。如果您在默认的 404 模板中包含异常消息,则存在向最终用户显示不合适的错误消息的风险。 【参考方案1】:

从 Django 1.9 开始,异常被传递给 page_not_found 视图,当您引发 Http404 时运行该视图。错误的表示被传递给模板,您可以将其包含在模板中:

 exception 

在早期版本中,异常不会传递给 page_not_found 视图,因此没有简单的方法将异常消息包含在模板中。

一种可能性是使用@Euribates 在他们的回答中建议的消息框架。另一个是渲染模板并在视图中返回 404 状态码,而不是引发 Http404

【讨论】:

exception 仅在 DEBUG 设置为 True 时呈现视图中设置的任何自定义消息。如果DEBUG = False,那么404.html中使用的 exception 只会渲染“Http404”。 @DanSwain 不确定我是否理解您的评论。如果 DEBUGTrue 则 Django 显示黄色页面未找到页面。如果DEBUGFalse,则默认视图会尝试显示来自异常的消息。如果您看到Http404,则可能在没有消息的情况下引发了异常,例如raise Http404. @Alasdair,这是我正在运行的代码:try:topic = Topic.objects.get(slug=slug)except Topic.DoesNotExist:raise Http404("Topic does not exist") 当我将DEBUG 设置为True,然后“主题不存在”显示在黄色错误页面中,但是如果我将DEBUG设置为False,那么标准404.html模板中的 exception 会呈现“Http404”,而不是“主题不存在”。 我刚刚用默认的page_not_found 404 处理程序仔细检查了 exception ,它肯定会在Django 2.0 中显示异常消息。如果您仍然无法使其正常工作,请提出一个包含足够详细信息的新问题以重现该问题。 如果您的消息被替换为默认消息(此处为 Http404),可能是因为您使用的是gettext_lazy() 而不是gettext()【参考方案2】:

还有另一种方法。 page_not_found 处的代码使用RequestContext;这意味着您可以访问由settings.py 中的TEMPLATE_CONTEXT_PROCESSORS 条目中定义的所有上下文处理器定义的所有变量。默认值包括django messages framework。

因此,例如,您可以使用messages.error 定义要显示的消息,并使用messages 变量在模板中显示消息。

换句话说,你可以这样写你的视图:

from django.contrib import messages
from django.http import Http404
from django.template import RequestContext

def my_view(request):
    # your code goes here
    if something_horribly_wrong_happened():
        messages.error(request, 'Somethig horribly wrong happened!')
        raise Http404("It doesn't mind whatever you put here")
    else:
        return render_to_response(
            'template.html',
            RequestContext(request, locals()),
            )

在您的 404.html 模板中,您应该编写如下内容:

% if messages %
<ul class="messages">
    % for message in messages %
    <li> message </li>
    % endfor %
</ul>
% endif %

它有点复杂,但它的优点是可以发送多条消息,甚至可以使用不同类型的消息(警告、调试、信息、错误等...)您可以阅读有关 django 消息框架的更多信息这里:The messages framework | Django Documentation。

【讨论】:

嗨,你能看看我的问题吗? ***.com/questions/66900041/…【参考方案3】:

我有更简单的解决方案

只需编写中间件,它会将您的错误文本放入某个请求变量中。看例子

from django.http.response import Http404

class Error404Middleware(object):
    def process_exception(self, request, exception):
        if isinstance(exception, Http404):
            request.error_404_message = exception.message

在 404.html 中

 request.error_404_message 

【讨论】:

【参考方案4】:

exception

从 1.9.6 开始,消息传递给:

raise Http404('msg')

可从templates/404.html 获得:

 exception 

来源:https://github.com/django/django/blob/1.9.6/django/views/defaults.py#L20

【讨论】:

嗨,你能看看我的问题吗? ***.com/questions/66900041/… @kd12345 感谢 ping,但恐怕我已经很久没有接触 Django 了 :-( 你介意我问一下你在 python 中使用什么 ORM 吗? @kd12345 我做的唯一 Python webdev 是 2014 年的一点 Django,所以我只是使用他们内置的 ORM。我认为这是体面的。现在我再次选择 webdev,但我正在查看是否有任何像样的 Node.js Web 框架可以更轻松地进行服务器端渲染。虽然有一段时间。 我刚刚开始学习 Django,因此我的问题可能看起来很业余。我实际上是从 Node.js 转移过来的。如果您使用 SQL,Sequelize 是一个非常强大的 ORM。我真的发现它使用起来非常简单流畅。

以上是关于如何在 Django 的自定义 404 错误模板中显示传递给 Http404 的消息?的主要内容,如果未能解决你的问题,请参考以下文章

木材是否有默认500模板,就像它有404?

我的自定义 Django 模板过滤器但没有任何其他过滤器的“无效过滤器”错误

“模板语法错误:过滤器无效:”;基于 django 文档的自定义 django 模板过滤器损坏,但模板标签有效

如何在我的自定义小部件模板中包含内置的 django 小部件模板?

如何使用页面应用程序中的自定义页面更改默认的 404 错误页面

Django - 如何在任何包含的模板中使用我的自定义过滤器?