末尾にスラッシュがないdjangoURLはリダイレクトされません


89

2台の別々のコンピューターに2つのアプリケーションがあります。コンピューター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ファイルで設定を確認してください

djangoドキュメントの詳細


4
「Trueに設定すると、リクエストURLがURLconfのどのパターンとも一致せず、スラッシュで終わらない場合、HTTPリダイレクトが同じURLに発行され、スラッシュが追加されます。リダイレクトにより、リダイレクトが発生する可能性があることに注意してください。 POSTリクエストで送信されたデータはすべて失われます。」「APPEND_SLASH設定は、CommonMiddlewareがインストールされている場合にのみ使用されます...」。よりクリーンなソリューションとしては、MichaelGendinの回答が好きです。
wtower 2015

3
urlpatternsの最後のエントリで追加の「catchall」URLを使用している場合、これは機能しません。@speedplaneの答えは、そのような状況でも機能します。ただし、もちろん、これはより単純であり、「すべてをキャッチ」するurlpatternエントリがない場合に使用する必要があります。
np8 2017

195

または、次のようにURLを記述できます。

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

末尾のスラッシュの後の疑問符は、正規表現ではオプションになります。何らかの理由でAPPEND_SLASH設定を使用したくない場合に使用します。


12
私をナイーブと呼んでください-しかし、なぜこの回答は100万の賛成票とdjangoのFAQのエントリを持っていないのですか?
Fergal Moran

42
SEOの理由でこれを実行したくないことは確かです。2つの有効なURLを使用するよりも、正規URLにリダイレクトする方が適切です。
ブライアンフランツ2012

47
Djangoを使用してRESTfulAPIを作成している場合、開発者がエンドポイントURLに直接データをPOSTするときに、これは優れたソリューションになる可能性があります。を使用しているときにAPPEND_SLASH、誤って末尾のスラッシュなしで送信し、urlconfが末尾のスラッシュ付きの場合、POSTリクエストをリダイレクトするときにデータが失われるという例外が発生します。
OrPo 2013年

5
このソリューションの問題は、2つのURLで同じページを提供していることです(末尾の有無にかかわらず/)-ずさんな、クローラーに悪い、保守が難しい、新しいシステムへの移行が難しい(見落としやすいため)
Jiaaro 2015年

いい答えだ。スラッシュは許可しない方がいいです(スラッシュは何かの終わりではなく、何か新しいものの始まりを意味するため(/ etcなど)、これにより標準(/ view)と非標準(/ view /)が可能になります。
David Betz 2015年

19

これは@MichaelGendinの答えを改善します。彼の答えは、2つの別々の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

これはregexでどのように機能しますか?元のURLは、例えば、クライアント名で正規表現に一致した場合
ニコロガスパリーニ

@NicolòGasparini-新しいバージョンのDjangoには、一致するすべてのURL引数とともにpattern_name使用されるredirect引数があります。
Tim Tisdall

2

私も同じ問題を抱えています。私のソリューションは、正規表現の終了行の前に(| /)を付けました。

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


1

リダイレクトせずにスラッシュ追加し、設定でCommonMiddlewareの代わりに使用します。Django2.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

私も同じ問題を抱えています。私の場合、それは静的ファイルの前からの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.