후행 슬래시가없는 django URL은 리디렉션되지 않습니다.


89

두 개의 별도 컴퓨터에 두 개의 응용 프로그램이 있습니다. 컴퓨터 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멈추고 mySite.com/login/컴퓨터 A 에서처럼 돌아 가지 않습니다 . 내가 놓친 것이 있습니까? 두 url.py파일 모두 나와 똑같아 보입니다.

답변:


103

APPEND_SLASHsettings.py 파일에서 설정을 확인하십시오.

장고 문서에 더 많은 정보


4
"True로 설정하면 요청 URL이 URLconf의 패턴과 일치하지 않고 슬래시로 끝나지 않으면 슬래시가 추가 된 동일한 URL로 HTTP 리디렉션이 실행됩니다. 리디렉션으로 인해 발생할 수 있습니다. POST 요청에 제출 된 모든 데이터가 손실됩니다. ". "APPEND_SLASH 설정은 CommonMiddleware가 설치된 경우에만 사용됩니다 ...". 나는 더 깨끗한 솔루션에 대한 Michael Gendin의 대답을 선호합니다.
Wtower

3
urlpatterns의 마지막 항목에서 추가 "catch all"url을 사용하는 경우 작동하지 않습니다. @speedplane의 대답은 이러한 상황에서도 작동합니다. 그러나 물론 이것은 더 간단하며 "catch all"urlpattern 항목이없는 경우에 사용해야합니다.
np8

195

또는 다음과 같이 URL을 작성할 수 있습니다.

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

후행 슬래시 뒤의 질문 기호는 정규 표현식에서 선택 사항입니다. 어떤 이유로 APPEND_SLASH 설정을 사용하지 않으려면 사용하십시오.


12
순진하다고 부르세요-그런데 왜이 답변이 백만 찬성표를 얻지 못했고 장고 FAQ에 항목이 없습니까?
Fergal Moran

42
SEO상의 이유로이 작업을 수행하고 싶지 않습니다. 유효한 URL이 두 개있는 것보다 표준 URL로 리디렉션하는 것이 좋습니다.
Brian Frantz

47
Django를 사용하여 RESTful API를 만드는 경우 개발자가 데이터를 끝점 URL에 직접 게시 할 때 좋은 솔루션이 될 수 있습니다. 를 사용할 때 APPEND_SLASH실수로 후행 슬래시없이 전송하고 urlconf에 후행 슬래시가있는 경우 POST 요청을 리디렉션 할 때 데이터 손실에 대한 예외가 발생합니다.
OrPo

5
이 솔루션의 문제점은 2 개의 URL (후행 포함 및 제외) 아래에서 동일한 페이지를 제공한다는 것입니다. /엉성하고 크롤러에게 좋지 않으며 유지 관리가 더 어렵고 새 시스템으로 마이그레이션하기가 더 어렵습니다 (간과하기 쉽기 때문에)
Jiaaro

좋은 대답입니다. 나는 슬래시를 허용하지 않는 것을 선호합니다 (이것은 무언가의 끝 (예 : / etc)이 아니라 새로운 무언가의 시작을 의미하기 때문에). 그러나 이것은 표준 (/ view)과 비표준 (/ view /)을 허용합니다.
David Betz 2015

19

이것은 @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"),
)

끝에 포괄 URL이있을 때 매우 유용합니다.
thclark

정규식과 어떻게 작동 할 수 있습니까? 원래 URL 예를 들어 클라이언트 이름이 정규식과 일치하는 경우
니콜로 가스 파리 니에게

@ NicolòGasparini-최신 버전의 Django에는 일치하는 모든 URL 인수 pattern_nameredirect함께 사용되는 인수가 있습니다.
Tim Tisdall

2

나도 같은 문제가 있었다. 내 솔루션은 정규 표현식의 끝 줄 앞에 (| /)를 넣었습니다.

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


1

redirect없이 슬래시 추가 하고 설정에서 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

나는 같은 문제가 있었다. 제 경우에는 staticfiles 이전의 urls.py의 일부 이전 버전에서 남은 오래된 버전이었습니다.

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

MEDIA_URL이 비어있어서이 패턴이 모든 것과 일치했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.