2017-07-04 2 views
1

J'utilise le LocaleMiddleware de Django pour internationaliser une partie du site sur lequel je travaille. Voici mon projet urls.py:Redirections de LocaleMiddleware sur un modèle d'URL non-i18n

from django.conf.urls import patterns, include, url 
from django.conf.urls.i18n import i18n_patterns 

urlpatterns = patterns('', 
    url(r'^api/stuff/(?P<stuff_id>)\d+/$', ApiStuff.as_view()), 
) 

urlpatterns += i18n_patterns('', 
    url(r'^stuff/', DoStuff.as_view()), 
) 

Le problème est, quand ApiStuff.as_view() renvoie une réponse 404 (autres codes d'erreur se comportent comme prévu), le LocaleMiddleware exploite la demande de faire rediriger vers /en/api/stuff/<stuff_id>, même si l'espace de noms /api est clairement pas dans le i18n_patterns (à la fin, il génère aussi une erreur 404, mais le contenu de ma réponse d'origine est perdu).

Voici le code de ApiStuff:

import django.http 
from django.views.generic import View 
from project.stuff.models import Stuff 


class ApiStuff(View): 

    @staticmethod 
    def get(request, *args, **kwargs): 
     stuff_id = kwargs['stuff_id'] 

     try: 
      stuff = Stuff.objects.get(pk=stuff_id) 
     except Stuff.DoesNotExist: 
      return response({"error": "stuff not found"}, 404) 

     result = stuff.serialize() 
     return response(result) 


def response(data, status=200): 
    data = json.dumps(data) 
    return django.http.HttpResponse(data, status=status, content_type='application/json') 

J'utilise django 1.6.10 (je sais, il est tard, mais je ne peux pas mettre à jour la version en ce moment).

Ai-je raté quelque chose?

+0

Avez-vous toujours le même problème, même si vous utilisez 'get_object_or_404'? Je me demande si le système se comporte différemment si l'exception 404 est propagée à travers les middlewares. – Risadinha

+0

@Risadinha oui, la redirection est la même avec 'get_object_or_404' – julienc

Répondre

1

Ceci est un vieux bug qui a été suivi ici:

https://code.djangoproject.com/ticket/17734

Le gestionnaire d'erreur 404 est un gestionnaire par défaut de Django. Il prend évidemment en compte la langue actuelle pour traduire le message "non trouvé".

Sauf si vous pouvez effectuer une mise à niveau vers une version plus récente, vous devez probablement définir votre propre gestionnaire d'erreurs (y compris route/URL).

EDIT:

Pour contourner ce problème, il pourrait être possible d'étendre la LocaleMiddleware et peut-être aussi CommonMiddleware. Cependant, il se pourrait que le gestionnaire 404 fasse néanmoins preuve de magie. Cela pourrait valoir la peine, car cela ne devrait nécessiter que quelques lignes de code.

Citant le billet:

lorsque vous demandez/api/collecte/404 /, il redirige l'utilisateur vers/en/api/collecte/404/(en supposant qu'il détecte la langue en). S'il teste avant de rediriger l'utilisateur si/fr/api/raise/404/est résolvable, il découvrira que cela déclencherait également un 404 et ne redirigerait donc pas l'utilisateur.

EDIT 2:

Comme alternative, vous pouvez tout simplement pas utiliser i18n_patterns et juste détecter/changer la langue via le navigateur/cookies/paramètres. Je l'ai fait pour un projet (qui comprenait Django CMS) où j'ai continué à rencontrer des problèmes avec ces URL. Ce n'est certainement pas une condition préalable pour que les sites Django localisés utilisent les modèles d'URL i18n. C'est juste quelque chose en haut, mais pas du tout nécessaire. La localisation fonctionnera très bien sans elle. Si vous avez besoin d'aide avec le middleware pour changer de langue, laissez un commentaire.

+0

En fait, j'ai vu ce ticket aussi, mais j'ai déjà vérifié que 1.6.10 était déjà patché à ce moment-là (cette version a été publiée en janvier 2015, et le billet a été fermé en 2012) – julienc

0

On peut contourner ce problème en utilisant suivant config url

urlpatterns += i18n_patterns(
    url(r'^(?!api.*)stuff', DoStuff.as_view()), 
)