it-swarm.com.ru

uRL-адреса Django без косой черты не перенаправляют

У меня есть два приложения, расположенные на двух разных компьютерах. На компьютере A в файле urls.py есть строка, подобная следующей: 

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

И этот URL будет работать как для mySite.com/cast/, так и mySite.com/cast. Но на компьютере B у меня есть аналогичный URL-адрес, написанный следующим образом:

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

По какой-то причине на компьютере B url mySite.com/login/будет работать, но mySite.com/login будет зависать и не будет возвращаться к mySite.com/login/, как на компьютере A. Есть ли что-то, что я пропустил? Оба файла url.py выглядят одинаково для меня.

68
whatWhat

проверьте настройки APPEND_SLASH в файле settings.py

больше информации в Django Docs

84
Jiaaro

Или вы можете написать свои URL, как это:

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

Знак вопроса после косой черты делает его необязательным в регулярном выражении. Используйте его, если по каким-либо причинам вы не хотите использовать настройку APPEND_SLASH.

163
Michael Gendin

Это улучшает ответ @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"),
)
13
speedplane

У меня тоже была такая же проблема. Мое решение было помещено (| /) перед конечной строкой моего регулярного выражения.

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

2
Atahualpa Silva Falcón

У меня была такая же проблема. В моем случае это был устаревший остаток какой-то старой версии в urls.py до статических файлов:

url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL.lstrip('/'),
    'Django.views.static.serve',
    kwargs={'document_root': settings.MEDIA_ROOT}),

MEDIA_URL был пуст, поэтому этот шаблон соответствовал всему.

0
janek37

Добавьте слеш без перенаправления , используйте его вместо 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
0
Max Tkachenko