web-dev-qa-db-fra.com

les URL Django sans slash final ne redirigent pas

J'ai deux applications situées sur deux ordinateurs distincts. Sur l'ordinateur A, dans le fichier urls.py, j'ai une ligne comme celle-ci: 

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

Et cette URL fonctionnera à la fois pour mySite.com/cast/ et mySite.com/cast. Mais sur l'ordinateur B, j'ai une URL similaire à celle-ci:

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

Pour une raison quelconque sur l'ordinateur B, le url mySite.com/login/fonctionnera, mais mySite.com/login sera bloqué et ne retournera pas directement à mySite.com/login/ comme cela fonctionnera sur l'ordinateur A. Y at-il quelque chose que j'ai oublié? Les deux fichiers url.py me semblent identiques.

68
whatWhat

vérifiez votre paramètre APPEND_SLASH dans le fichier settings.py

plus d'informations dans la documentation Django

84
Jiaaro

Ou vous pouvez écrire vos URL comme ceci:

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

Le signe de la question après la barre oblique le rend facultatif dans regexp. Utilisez-le si, pour certaines raisons, vous ne souhaitez pas utiliser le paramètre APPEND_SLASH.

163
Michael Gendin

Cela améliore la réponse de @Michael Gendin. Sa réponse sert la même page avec deux URL distinctes. Il serait préférable que login redirige automatiquement vers login/, puis serve ce dernier comme page principale:

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

J'ai eu le même problème. Dans mon cas, c’était un reliquat de certaines anciennes versions de urls.py, d’avant staticfiles:

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

MEDIA_URL était vide, ce modèle correspond donc à tout.

0
janek37

Ajouter une barre oblique sans redirection , utilisez-la à la place de CommonMiddleware dans les paramètres, Django 2.1:

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

Ajoutez à votre répertoire principal 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