42 votes

Urls insensibles à la casse pour Django ?

Il semble que par défaut, le résolveur d'url de Django effectue une recherche sensible à la casse pour résoudre l'url et fait la différence entre '/Login' et 'login'. Mes modèles d'url sont les suivants.

urlpatterns = patterns('',
    (r'^admin/(.*)', admin.site.root),
    (r'^static/(?P<path>.*)$', 'django.views.static.serve',
        {'document_root': settings.STATIC_DOC_ROOT, 'show_indexes': True}),
    (r'^login/$', 'django.contrib.auth.views.login'),
    (r'^logout/$', do_logout),
)

Est-ce que quelqu'un peut me guider, comment rendre les urls de django insensibles à la casse ?

91voto

Alex Martelli Points 330805

Mettez juste (?i) au début de chaque r'...' chaîne de caractères, c'est-à-dire :

urlpatterns = patterns('',
(r'^(?i)admin/(.*)', admin.site.root),
(r'^(?i)static/(?P<path>.*)$', 'django.views.static.serve',
    {'document_root': settings.STATIC_DOC_ROOT, 'show_indexes': True}),
(r'^(?i)login/$', 'django.contrib.auth.views.login'),
(r'^(?i)logout/$', do_logout),
)

de dire à chaque RE de correspondre au cas par cas - et, bien sûr, de vivre heureux pour toujours !-)

20voto

notsofast Points 351

Dans Django 2.1, il apparaît que (?i) placé partout dans l'expression rationnelle de l'URL lui fera ignorer la casse. Cependant, reverse() échoue à moins que le (?i) suit le $ à la fin de l'expression rationnelle.

from django.urls import re_path, reverse
from django.shortcuts import render

def home_page(request):
    foo = reverse('home_page')
    return render(request, 'home.html')

urlpatterns = [ re_path(r'home/(?i)', home_page, name='home_page') ]

soulève

ValueError: Non-reversible reg-exp portion: '(?i'

mais fonctionne proprement avec la regex r'home/$(?i)' .

4voto

Sym Points 55

Mise à jour de Django 2.2

Selon ce billet :

La prise en charge des drapeaux en ligne dans les groupes d'expressions régulières ((?i), (?L), (?m), (?s) et (?u)) a été dépréciée dans Django 1.11 et supprimée dans Django 2.1.

Dans Django 2.2, on ajoute (?i) au début d'un motif produit cette exception :

ValueError: Non-reversible reg-exp portion

confusément, l'ajouter à la fin produit cet avertissement :

DeprecationWarning: Flags not at the start of the expression

La nouvelle méthode proposée pour gérer les URL insensibles à la casse dans Django est d'utiliser un fichier Gestionnaire 404 personnalisé .

Pour information, ce billet suggère également que "les URL insensibles à la casse ne sont pas une bonne pratique", mais il ne fournit pas plus d'arguments pour cela.

Il existe un paquet sur PyPi appelé django-icase cela semble être une bonne option

2voto

chrki Points 4592

Avec Django 2.0 (publié en décembre 2017), la manière recommandée d'utiliser les expressions régulières pour la correspondance d'URL est désormais la suivante. re_path au lieu de url :

from django.urls import path, re_path
from . import views

urlpatterns = [   
    re_path(r'^(?i)admin/(.*)', admin.site.root),
    re_path(r'^(?i)something/(?P<somestring>\w+)/$', views.something),
    re_path(r'^(?i)login/$', views.login),
    re_path(r'^(?i)logout/$', views.logout),
]

0voto

Danut Popa Points 79

Vous pourriez également gérer cela depuis votre vue. Par exemple, si vous disposez d'une vue générique DetailView, vous pouvez remplacer l'option get_queryset et définir la méthode limace en minuscules :

models.py :

from django.db import models
from django.utils.text import slugify

class MyModel(models.Model):
    """MyModel

    """  
    # name attribute is used to generate slug
    name = models.CharField(max_length=25, verbose_name='Name', unique=True)

    slug = models.SlugField(unique=True, verbose_name='Slug')

    # override save method to generate slug
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        self.slug = slugify(self.name)
        super(MyModel, self).save(force_insert=False, force_update=force_update, using=using, update_fields=update_fields)

views.py :

from django.views import generic

class MyModelDetailView(generic.DetailView):
    """MyModelDetailView

        Detail view of MyObject.
    """

    model = MyModel
    template_name = 'my_models/my_model_detail.html'

    def get_queryset(self):
        try:
            self.kwargs['slug'] = self.kwargs['slug'].lower()
        except Exception as err:
            print(err)
            pass

        queryset = self.model.objects.filter()
        return queryset

urls.py :

from . import views
from django.conf.urls import url

    url(r'^my_model_detail/(?P<slug>[-\w]+)/$', views.MyModelDetailView.as_view(),
        name='my_model_detail'),

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X