没有尾部斜杠的 django url 不会重定向

发布于 2024-08-08 06:52:30 字数 506 浏览 5 评论 0原文

我有两个应用程序位于两台不同的计算机上。在计算机 A 上,在 urls.py 文件中,我有一行如下所示的行:

(r'^cast/$', 'mySite.simulate.views.cast')

并且该 url 适用于 mySite.com/cast/mySite .com/cast。但在计算机 BI 上,有一个类似的 url 写法如下:

(r'^login/$', 'mySite.myUser.views.login')

出于某种原因,在计算机 B 上,url mySite.com/login/ 可以工作,但 mySite.com/login 将挂起并且不会像在计算机 A 上那样直接返回 mySite.com/login/。我是否错过了什么?在我看来,两个 url.py 文件看起来都一样。

I've got two applications located on two separate computers. On computer A, in the urls.py file I have a line like the following:

(r'^cast/

And that url will work for both mySite.com/cast/ and mySite.com/cast. But on computer B I have a similar url written out like:

(r'^login/

For some reason on computer B the url mySite.com/login/ will work but mySite.com/login will hang and won't direct back to mySite.com/login/ like it will on computer A. Is there something I missed? Both url.py files look identical to me.

, 'mySite.simulate.views.cast')

And that url will work for both mySite.com/cast/ and mySite.com/cast. But on computer B I have a similar url written out like:


For some reason on computer B the url mySite.com/login/ will work but mySite.com/login will hang and won't direct back to mySite.com/login/ like it will on computer A. Is there something I missed? Both url.py files look identical to me.

, 'mySite.myUser.views.login')

For some reason on computer B the url mySite.com/login/ will work but mySite.com/login will hang and won't direct back to mySite.com/login/ like it will on computer A. Is there something I missed? Both url.py files look identical to me.

, 'mySite.simulate.views.cast')

And that url will work for both mySite.com/cast/ and mySite.com/cast. But on computer B I have a similar url written out like:

For some reason on computer B the url mySite.com/login/ will work but mySite.com/login will hang and won't direct back to mySite.com/login/ like it will on computer A. Is there something I missed? Both url.py files look identical to me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

日暮斜阳 2024-08-15 06:52:30

或者您可以这样编写您的网址:

(r'^login/?

尾部斜杠后面的问号使其在正则表达式中是可选的。如果由于某些原因您不想使用 APPEND_SLASH 设置,请使用它。

, 'mySite.myUser.views.login')

尾部斜杠后面的问号使其在正则表达式中是可选的。如果由于某些原因您不想使用 APPEND_SLASH 设置,请使用它。

Or you can write your urls like this:

(r'^login/?

The question sign after the trailing slash makes it optional in regexp. Use it if for some reasons you don't want to use APPEND_SLASH setting.

, 'mySite.myUser.views.login')

The question sign after the trailing slash makes it optional in regexp. Use it if for some reasons you don't want to use APPEND_SLASH setting.

说谎友 2024-08-15 06:52:30

检查 settings.py 文件中的 APPEND_SLASH 设置

django 文档中的更多信息

check your APPEND_SLASH setting in the settings.py file

more info in the django docs

久而酒知 2024-08-15 06:52:30

这改进了@Michael Gendin 的答案。他的回答提供了具有两个不同 URL 的相同页面。最好让 login 自动重定向到 login/,然后将后者作为主页:

from django.conf.urls import patterns
from django.views.generic import RedirectView

urlpatterns = patterns('',
    # Redirect login to login/
    (r'^login
, RedirectView.as_view(url = '/login/')),
    # Handle the page with the slash.
    (r'^login/', "views.my_handler"),
)

This improves on @Michael Gendin's answer. His answer serves the identical page with two separate URLs. It would be better to have login automatically redirect to login/, and then serve the latter as the main page:

from django.conf.urls import patterns
from django.views.generic import RedirectView

urlpatterns = patterns('',
    # Redirect login to login/
    (r'^login
, RedirectView.as_view(url = '/login/')),
    # Handle the page with the slash.
    (r'^login/', "views.my_handler"),
)
再浓的妆也掩不了殇 2024-08-15 06:52:30

我也遇到过同样的问题。我的解决方案是在正则表达式的结束行之前放置一个(|/)。

url(r'^artists/(?P[\d]+)(|/)$', ArtistDetailView.as_view()),

I've had the same problem too. My solution was put an (|/) before the end line of my regular expression.

url(r'^artists/(?P[\d]+)(|/)$', ArtistDetailView.as_view()),

心碎无痕… 2024-08-15 06:52:30

附加斜杠不重定向,在设置中使用它代替 CommonMiddleware,Django 2.1:

MIDDLEWARE = [
    ...
    # 'django.middleware.common.CommonMiddleware',
    'htx.middleware.CommonMiddlewareAppendSlashWithoutRedirect',
    ...
]

添加到您的主应用程序目录middleware.py

from django.http import HttpResponsePermanentRedirect, HttpRequest
from django.core.handlers.base import BaseHandler
from django.middleware.common import CommonMiddleware
from django.conf import settings


class HttpSmartRedirectResponse(HttpResponsePermanentRedirect):
    pass


class CommonMiddlewareAppendSlashWithoutRedirect(CommonMiddleware):
    """ This class converts HttpSmartRedirectResponse to the common response
        of Django view, without redirect.
    """
    response_redirect_class = HttpSmartRedirectResponse

    def __init__(self, *args, **kwargs):
        # create django request resolver
        self.handler = BaseHandler()

        # prevent recursive includes
        old = settings.MIDDLEWARE
        name = self.__module__ + '.' + self.__class__.__name__
        settings.MIDDLEWARE = [i for i in settings.MIDDLEWARE if i != name]

        self.handler.load_middleware()

        settings.MIDDLEWARE = old
        super(CommonMiddlewareAppendSlashWithoutRedirect, self).__init__(*args, **kwargs)

    def process_response(self, request, response):
        response = super(CommonMiddlewareAppendSlashWithoutRedirect, self).process_response(request, response)

        if isinstance(response, HttpSmartRedirectResponse):
            if not request.path.endswith('/'):
                request.path = request.path + '/'
            # we don't need query string in path_info because it's in request.GET already
            request.path_info = request.path
            response = self.handler.get_response(request)

        return response

Append slash without redirect, use it instead of CommonMiddleware in settings, Django 2.1:

MIDDLEWARE = [
    ...
    # 'django.middleware.common.CommonMiddleware',
    'htx.middleware.CommonMiddlewareAppendSlashWithoutRedirect',
    ...
]

Add to your main app directory middleware.py:

from django.http import HttpResponsePermanentRedirect, HttpRequest
from django.core.handlers.base import BaseHandler
from django.middleware.common import CommonMiddleware
from django.conf import settings


class HttpSmartRedirectResponse(HttpResponsePermanentRedirect):
    pass


class CommonMiddlewareAppendSlashWithoutRedirect(CommonMiddleware):
    """ This class converts HttpSmartRedirectResponse to the common response
        of Django view, without redirect.
    """
    response_redirect_class = HttpSmartRedirectResponse

    def __init__(self, *args, **kwargs):
        # create django request resolver
        self.handler = BaseHandler()

        # prevent recursive includes
        old = settings.MIDDLEWARE
        name = self.__module__ + '.' + self.__class__.__name__
        settings.MIDDLEWARE = [i for i in settings.MIDDLEWARE if i != name]

        self.handler.load_middleware()

        settings.MIDDLEWARE = old
        super(CommonMiddlewareAppendSlashWithoutRedirect, self).__init__(*args, **kwargs)

    def process_response(self, request, response):
        response = super(CommonMiddlewareAppendSlashWithoutRedirect, self).process_response(request, response)

        if isinstance(response, HttpSmartRedirectResponse):
            if not request.path.endswith('/'):
                request.path = request.path + '/'
            # we don't need query string in path_info because it's in request.GET already
            request.path_info = request.path
            response = self.handler.get_response(request)

        return response
你げ笑在眉眼 2024-08-15 06:52:30

在某些情况下,当我们的某些用户以不同的结尾调用 API 时,我们会遇到问题。通常,我们的用户使用 Postman 来实现这一点,并且不担心端点处的斜线。结果,我们收到了支持问题请求,因为用户忘记在 POST 请求末尾附加斜杠 /

我们通过使用适用于 Django 3.2+Django 4.0+ 的自定义中间件解决了这个问题。之后,Django 可以处理任何带斜杠或不带斜杠的 API 的 POST/PUT/DELETE 请求。使用此中间件不需要更改settings.py中的APPEND_SLASH属性

因此,在settings.py中需要删除当前的'django.middleware.common.CommonMiddleware' 并插入新的中间件。确保在下面的示例中将 your_project_name 更改为您的真实项目名称。

MIDDLEWARE = [
...
  # 'django.middleware.common.CommonMiddleware',
    'your_project_name.middleware.CommonMiddlewareAppendSlashWithoutRedirect',
...
]

添加到您的主应用程序目录 middleware.py:

from django.http import HttpResponsePermanentRedirect, HttpRequest
from django.core.handlers.base import BaseHandler
from django.middleware.common import CommonMiddleware
from django.utils.http import escape_leading_slashes
from django.conf import settings


class HttpSmartRedirectResponse(HttpResponsePermanentRedirect):
    pass


class CommonMiddlewareAppendSlashWithoutRedirect(CommonMiddleware):
    """ This class converts HttpSmartRedirectResponse to the common response
            of Django view, without redirect. This is necessary to match status_codes
            for urls like /url?q=1 and /url/?q=1. If you don't use it, you will have 302
            code always on pages without slash.
    """
    response_redirect_class = HttpSmartRedirectResponse

def __init__(self, *args, **kwargs):
    # create django request resolver
    self.handler = BaseHandler()

    # prevent recursive includes
    old = settings.MIDDLEWARE
    name = self.__module__ + '.' + self.__class__.__name__
    settings.MIDDLEWARE = [i for i in settings.MIDDLEWARE if i != name]

    self.handler.load_middleware()

    settings.MIDDLEWARE = old
    super(CommonMiddlewareAppendSlashWithoutRedirect, self).__init__(*args, **kwargs)

def get_full_path_with_slash(self, request):
    """ Return the full path of the request with a trailing slash appended
        without Exception in Debug mode
    """
    new_path = request.get_full_path(force_append_slash=True)
    # Prevent construction of scheme relative urls.
    new_path = escape_leading_slashes(new_path)
    return new_path

def process_response(self, request, response):
    response = super(CommonMiddlewareAppendSlashWithoutRedirect, self).process_response(request, response)

    if isinstance(response, HttpSmartRedirectResponse):
        if not request.path.endswith('/'):
            request.path = request.path + '/'
        # we don't need query string in path_info because it's in request.GET already
        request.path_info = request.path
        response = self.handler.get_response(request)

    return response

这个答案可能看起来类似于 马克斯·特卡琴科回答。但他的代码在最新版本的 Django 中对我不起作用。

In some cases, we have issues when some of our users call API with different endings. Usually, our users use Postman for that and are not worried about slash at the endpoint. As result, we receive issue requests in support, because users forgot to append a slash / at the end of POST requests.

We solved it by using a custom middleware that works for us in Django 3.2+ and Django 4.0+. After that, Django may handle any POST/PUT/DELETE requests to your API with slash or without them. With this middleware unneeded to change APPEND_SLASH property in settings.py

So, in the settings.py need to remove your current 'django.middleware.common.CommonMiddleware' and insert new middleware. Make sure, you change your_project_name in my example below on your real project name.

MIDDLEWARE = [
...
  # 'django.middleware.common.CommonMiddleware',
    'your_project_name.middleware.CommonMiddlewareAppendSlashWithoutRedirect',
...
]

Add to your main app directory middleware.py:

from django.http import HttpResponsePermanentRedirect, HttpRequest
from django.core.handlers.base import BaseHandler
from django.middleware.common import CommonMiddleware
from django.utils.http import escape_leading_slashes
from django.conf import settings


class HttpSmartRedirectResponse(HttpResponsePermanentRedirect):
    pass


class CommonMiddlewareAppendSlashWithoutRedirect(CommonMiddleware):
    """ This class converts HttpSmartRedirectResponse to the common response
            of Django view, without redirect. This is necessary to match status_codes
            for urls like /url?q=1 and /url/?q=1. If you don't use it, you will have 302
            code always on pages without slash.
    """
    response_redirect_class = HttpSmartRedirectResponse

def __init__(self, *args, **kwargs):
    # create django request resolver
    self.handler = BaseHandler()

    # prevent recursive includes
    old = settings.MIDDLEWARE
    name = self.__module__ + '.' + self.__class__.__name__
    settings.MIDDLEWARE = [i for i in settings.MIDDLEWARE if i != name]

    self.handler.load_middleware()

    settings.MIDDLEWARE = old
    super(CommonMiddlewareAppendSlashWithoutRedirect, self).__init__(*args, **kwargs)

def get_full_path_with_slash(self, request):
    """ Return the full path of the request with a trailing slash appended
        without Exception in Debug mode
    """
    new_path = request.get_full_path(force_append_slash=True)
    # Prevent construction of scheme relative urls.
    new_path = escape_leading_slashes(new_path)
    return new_path

def process_response(self, request, response):
    response = super(CommonMiddlewareAppendSlashWithoutRedirect, self).process_response(request, response)

    if isinstance(response, HttpSmartRedirectResponse):
        if not request.path.endswith('/'):
            request.path = request.path + '/'
        # we don't need query string in path_info because it's in request.GET already
        request.path_info = request.path
        response = self.handler.get_response(request)

    return response

This answer may look similar to Max Tkachenko answer. But his code didn't work for me in the latest versions of Django.

疯了 2024-08-15 06:52:30

我也遇到过同样的问题。就我而言,它是 urls.py 中旧版本的旧版本,来自 staticfiles:

url(r'^%s(?P<path>.*)

MEDIA_URL 为空,因此该模式与所有内容匹配。

% settings.MEDIA_URL.lstrip('/'), 'django.views.static.serve', kwargs={'document_root': settings.MEDIA_ROOT}),

MEDIA_URL 为空,因此该模式与所有内容匹配。

I've had the same problem. In my case it was a stale leftover from some old version in urls.py, from before staticfiles:

url(r'^%s(?P<path>.*)

MEDIA_URL was empty, so this pattern matched everything.

% settings.MEDIA_URL.lstrip('/'), 'django.views.static.serve', kwargs={'document_root': settings.MEDIA_ROOT}),

MEDIA_URL was empty, so this pattern matched everything.

小瓶盖 2024-08-15 06:52:30

在 Django 项目的设置文件 (settings.py) 中,确保 APPEND_SLASH 设置为 True:

APPEND_SLASH = True

接下来,将 CommonMiddleware 添加到 MIDDLEWARE 设置:

MIDDLEWARE = [
    # other middleware classes...
    'django.middleware.common.CommonMiddleware',
    # other middleware classes...
]

通过此配置,Django 的 CommonMiddleware 将自动处理 URL 重定向并添加或删除尾部斜杠根据需要。这意味着 Django REST Framework 将正确处理对“xyz/”和“xyz”的请求。

注意 - 发出请求时,通常建议包含尾部斜杠以符合 RESTful 约定。但是,通过上述配置,不带尾部斜杠的请求仍将按预期工作。

In your Django project's settings file (settings.py), make sure the APPEND_SLASH setting is set to True:

APPEND_SLASH = True

Next, add the CommonMiddleware to the MIDDLEWARE setting:

MIDDLEWARE = [
    # other middleware classes...
    'django.middleware.common.CommonMiddleware',
    # other middleware classes...
]

With this configuration, Django's CommonMiddleware will automatically handle URL redirection and add or remove the trailing slash as needed. This means that requests to both 'xyz/' and 'xyz' will be correctly processed by Django REST Framework.

Note - When making requests, it is generally recommended to include the trailing slash to conform to RESTful conventions. However, with the above configuration, requests without the trailing slash will still work as expected.

翻身的咸鱼 2024-08-15 06:52:30

您可以使用此代码段

 from django.urls import re_path, path
 from django.urls.resolvers import _route_to_regex
 def tr_path(route, view, *args, **kwargs):
    if callable(view):
       r = _route_to_regex(route)
       if r[0][-1] != '/':
          new_route = r[0] + '/?

,然后将您的 path 替换为 tr_path

# add trailed slash return re_path(new_route, view, *args, **kwargs) return path(route, view, *args, **kwargs)

,然后将您的 path 替换为 tr_path

You can use this snippet

 from django.urls import re_path, path
 from django.urls.resolvers import _route_to_regex
 def tr_path(route, view, *args, **kwargs):
    if callable(view):
       r = _route_to_regex(route)
       if r[0][-1] != '/':
          new_route = r[0] + '/?

then replace your path totr_path

# add trailed slash return re_path(new_route, view, *args, **kwargs) return path(route, view, *args, **kwargs)

then replace your path totr_path

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文