【问题标题】:Django - remove www from URLsDjango - 从 URL 中删除 www
【发布时间】:2014-12-09 04:22:50
【问题描述】:

我已将此添加到我的.htacces

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

但随后尝试联系www.example.com 会将我重定向到:

http://example.com/example/wsgi.py/

因为我的 httpd.conf 中有 WSGIScriptAlias / home/www/example.com/example/wsgi.py 指令,当然我得到 404 错误。

最终,我设法通过在urls.py 中添加下一行来修复这个问题:

url(r'^example/wsgi.py/$', index),(因此重定向到主页)

但我不太确定这是正确的方法(因为当我尝试访问example.com 时,我看到网络浏览器将地址快速更改为www.example.com,然后再次更改为example.com

如果有人会问,是的,我见过this,但这也对我没有帮助,因为浏览器出现 url 递归问题(example.com/example.com/example.com/example.com/example. com...)

编辑:文件夹结构

这是我的文件夹结构:

\mysite\ static\ media\ .htaccess manage.py mysite\ templates templatetags tinymce static urls.py settigs.py views.py wsgi.py models.py forms.py __init__.py

【问题讨论】:

    标签: django apache .htaccess no-www


    【解决方案1】:

    适用于 Django 1.11+ 风格中间件的修改版本:

    from django.http import HttpResponsePermanentRedirect
    
    class NoWWWRedirectMiddleware:
        def __init__(self, get_response=None):
            self.get_response = get_response
    
        def __call__(self, request):
            response = self.process_request(request)
            return response or self.get_response(request)
    
        def process_request(self, request):
            host = request.get_host()
            if host.startswith('www.'):
                if request.method == 'GET':
                    no_www = host[4:]
                    url = request.build_absolute_uri().replace(host, no_www, 1)
                        return HttpResponsePermanentRedirect(url)
    

    【讨论】:

      【解决方案2】:

      我知道这已经回答了一段时间,但要添加到上面给出的答案中使用

      host.startswith('www.')
      

      它更具可读性,而且您应该使用永久重定向来为浏览器提供正确的响应标头。

      from django import http
      
      class NoWWWRedirectMiddleware(object):
          def process_request(self, request):
              host = request.get_host()
              if host.startswith('www.'):
                  if request.method == 'GET':  # if wanna be a prefect REST citizen, consider HEAD and OPTIONS here as well
                      no_www_host = host[4:]
                      url = request.build_absolute_uri().replace(host, no_www_host, 1)
                      return http.HttpResponsePermanentRedirect(url)
      

      【讨论】:

        【解决方案3】:

        我发现使用中间件完成无 www 重定向要比使用 Apache mod_rewrite 配置简单得多。

        您链接到的中间件看起来可以解决问题。我猜你的问题来自 Apache 配置 - 确保删除所有 mod_rewrite 命令(Rewrite* 东西),然后重新启动 apache 服务器(参考Apache docs 但检查你的操作系统,可能是特定的)。

        您只需要进行一项额外的调整:确保您不重定向任何 POST 请求,因为这可能会导致数据丢失(切线参考:Why doesn't HTTP have POST redirect?)。

        无论如何,这是我使用的,对我来说效果很好:

        from django.http import HttpResponseRedirect
        
        class NoWWWRedirectMiddleware(object):
            def process_request(self, request):
        
            if request.method == 'GET':  # if wanna be a prefect REST citizen, consider HEAD and OPTIONS here as well
                host = request.get_host()
                if host.lower().find('www.') == 0:
                    no_www_host = host[4:]
                    url = request.build_absolute_uri().replace(host, no_www_host, 1)
                    return HttpResponseRedirect(url)
        

        要使用它,请在某处放置一个文件,也许是mysite/mysite/middleware.py。 然后确保它在您的settings.py 中运行:

        MIDDLEWARE_CLASSES = (
            'mysite.middleware.NoWWWRedirectMiddleware',
            # ... other middleware ...
        

        如果您的settings.py 中没有MIDDLEWARE_CLASSES,则从here in the Django docs 复制默认值,但让您看到的是正确版本的Django,1.7 中有一些变化!

        【讨论】:

        • 感谢您的详尽解答和解释!我已经按照您的建议进行了尝试,但我仍然遇到问题:使用此中间件,我可以在点击“www.example.com”时打开我的网站,但只是“example.com”返回此错误:Traceback (most recent call last): File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 90, in get_response response = middleware_method(request) TypeError: process_request() takes exactly 5 arguments (2 given)
        • @frnhr:从不同的角度来看,与在 Web 服务器级别相比,在中间件中执行此操作会更好(性能方面)吗?
        • 性能方面,最好在服务器堆栈中更早地执行此操作(在 Apache、nginx 或您拥有的任何设备上)。还要确保它是永久重定向,感谢 user1940979 指出这一点,请参阅下面的答案。
        【解决方案4】:

        这个 Apache 配置对我有用:

        RewriteEngine On
        RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]
        RewriteRule ^(.*)$ http://example.com$1 [R=301,L]
        
        WSGIScriptAlias / /home/www/example.com/example/wsgi.py
        WSGIPythonPath /home/www/example.com/example
        
        <Directory /home/www/example.com/example>
          <Files wsgi.py>
            Require all granted
          </Files>
        </Directory>
        

        【讨论】:

        • 我无法使用WSGIPythonPath /home/www/example.com/example 重新启动 Apache 服务器。其次,我不得不将Require all granted 更改为Order deny,allow Allow from all,因为我运行的是2.2 apache。第三,如果我删除 WSGIPythonPath /home/www/example.com/example apache 能够重新启动,但点击 www.example.com 仍然会给我 example.com/example/wsgi.py :(
        • 如果在 confid 中使用 WSGIPythonPath 会出现什么错误?您能否在您的问题中描述您的应用的文件夹结构?
        • 不幸的是,我不知道是什么类型的错误,因为我通过 Webuzo 控制面板重新启动服务。它只显示“服务无法重新启动”。我如何检查是什么类型的错误?对不起,我是 apache 的菜鸟。我已经添加了我的文件夹结构。
        猜你喜欢
        • 2018-09-18
        • 1970-01-01
        • 2016-10-01
        • 2013-12-02
        • 1970-01-01
        • 2017-03-31
        • 2011-09-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多