【问题标题】:Django utf-8 urlsDjango utf-8 网址
【发布时间】:2020-01-05 08:17:26
【问题描述】:

我有一个 Django 应用程序,可以在 localhost 上正常工作。即使是 utf-8 URL 路径。但是当我在生产中使用它时,它会给我一个错误:

2019-09-01 14:32:09.558237 [ERROR] [12257] wsgiAppHandler pApp->start_response() return NULL.
Traceback (most recent call last):
File "/home/medualla/virtualenv/project/3.7/lib/python3.7/site-packages/django/core/handlers/wsgi.py", line 139, in call 
set_script_prefix(get_script_name(environ))
File "/home/medualla/virtualenv/project/3.7/lib/python3.7/site-packages/django/core/handlers/wsgi.py", line 179, in get_script_name
script_url = get_bytes_from_wsgi(environ, 'SCRIPT_URL', '') or get_bytes_from_wsgi(environ, 'REDIRECT_URL', '')
File "/home/medualla/virtualenv/project/3.7/lib/python3.7/site-packages/django/core/handlers/wsgi.py", line 204, in get_bytes_from_wsgi
return value.encode('iso-8859-1')
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 1-6: ordinal not in range(256)

当我尝试像
http://meduallameh.ir/صفحه
这样的网址时会发生此错误 我得到的唯一答案是网络服务器的问题。我将它部署在共享主机上,我问他们,他们告诉我 Web 服务器支持 utf-8。现在我需要一些帮助来解决这个问题。

【问题讨论】:

  • 您的服务器配置是什么?你运行的是 apache 还是 nginx? gunicorn 还是 uwsgi?
  • 请注意,浏览器将此 URI 发送为 http://meduallameh.ir/%D8%B5%D9%81%D8%AD%D9%87,HTTP 仅支持 ASCII 字符,因此 URL 被编码。您的 Web 服务器(例如 apache)应该只将此编码的 URL 传递给您的 wsgi worker,所以这会是一个问题很奇怪。
  • @dirkgroten 我告诉过网络服务器是 LiteSpeed 并且我不知道配置。我正在使用 CPanel 设置 python 应用程序部分。我向主机提供商发送了一张票,他们说网络服务器很好,很多人对此没有问题。
  • @dirkgroten 是的,我很困惑,为什么会这样。将其更改为 ASCII 但 Django 抛出错误
  • 仍然需要知道正在使用什么 wsgi 服务器。 LiteSpeed 只是一个网络服务器。

标签: django django-views django-urls litespeed


【解决方案1】:

有一次,我的 URL 中有 UTF-8 字符为我工作,不知何故,我注意到当我从 Python 2 迁移到 Python 3 时它坏了(一路上,我也从 Apache + mod_wsgi 切换到Apache 代理到 Gunicorn)。

根据 OP 提供的答案,我不情愿地采用子类化默认的 WSGIHandler 和 WSGIRequest。

要点:https://gist.github.com/jontsai/afd5f5d9399ac2b0d770a73983d61690#file-django_wsgi_utf8_handler-py-L66-L69

虽然不理想,但此解决方案可以部署到多个服务器/环境。

我将尝试向 Django 项目提交补丁。

【讨论】:

    【解决方案2】:

    在处理了一些代码并搜索了问题后,我发现问题是 SCRIPT_URL 和其他内容在主机中默认解码为 utf-8。所以它给出了一个错误。我通过将 get_bytes_from_wsgi return 语句更改为此临时修复它;

    def get_bytes_from_wsgi(environ, key, default):
        """
        Get a value from the WSGI environ dictionary as bytes.
    
        key and default should be strings.
        """
        value = environ.get(key, default)
        # Non-ASCII values in the WSGI environ are arbitrarily decoded with
        # ISO-8859-1. This is wrong for Django websites where UTF-8 is the default.
        # Re-encode to recover the original bytestring.
        return value.encode('utf-8')
    

    所以问题解决了(现在)。我发现这发生在许多标题上,尤其是文件。如果有人找到其他可以修复的方法,请写在这里

    【讨论】:

    • 处理类似的问题,但我宁愿不必编辑 Django 库代码。
    • @jontsai 我同意你的看法。如果您有权访问 Web 服务器,则可以将 Web 服务器的默认编码更改为 ISO-8859-1。如果没有,您必须联系管理员。
    • 这简直令人震惊。我试图弄清楚如何向 Django 提交补丁。我的网络服务器是 Apache 并且代理到 Gunicorn for WSGI。我仍在尝试找出在哪里配置我的网络服务器以使用 ISO-8859-1,但是按照您现在所做的那样修补 Django wsgi.py 文件。
    • 我最终创建了一个新文件并将 WSGIHandler 和 WSGIRequest 子类化,然后将我的 WSGI 入口点指向我的自定义 WSGI 处理程序,而不是修改 Django 库代码。这样,我可以可靠地将解决方案部署到各种服务器/主机。要点:gist.github.com/jontsai/…
    猜你喜欢
    • 2013-05-10
    • 2013-10-17
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多