Case insensitive urls for Django?

前端 未结 5 1826
野的像风
野的像风 2020-12-04 22:14

It seems by default django\'s url solver perform case sensitive search for solving url and differentiate between \'/Login\' and \'login\'. My url patterns are as follows.

相关标签:
5条回答
  • 2020-12-04 22:20

    Django 2.2 update

    According to this ticket:

    Support for inline flags in regular expression groups ((?i), (?L), (?m), (?s), and (?u)) was deprecated in Django 1.11 and removed in Django 2.1

    In Django 2.2 adding (?i) to the start of a pattern produces this exception:

    ValueError: Non-reversible reg-exp portion

    confusingly, adding it to the end produces this warning:

    DeprecationWarning: Flags not at the start of the expression

    The new suggested way to handle case insensative URLs in Django is to use a custom 404 handler.

    FWIW, that ticket also suggests "case-insensitive URLs aren't a good practice", however it doesn't provide any more arguement for this.

    There is a package on PyPi called django-icase that looks like a good option

    0 讨论(0)
  • 2020-12-04 22:23

    You could also manage this from your view. For instance, if you have a generic.DetailView, you could override get_queryset method and set the slug value to lower case:

    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'),
    
    0 讨论(0)
  • 2020-12-04 22:34

    In Django 2.1, it appears that (?i) placed anywhere inside the URL regex will cause it to ignore case. However, reverse() fails unless the (?i) follows the $ at the end of the regex.

    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') ]
    

    raises

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

    but runs cleanly with the regex r'home/$(?i)'.

    0 讨论(0)
  • 2020-12-04 22:37

    With Django 2.0 (released in December 2017) the recommended way to use regular expressions for URL-matching is now re_path instead of 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),
    ]
    
    0 讨论(0)
  • 2020-12-04 22:41

    Just put (?i) at the start of every r'...' string, i.e.:

    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),
    )
    

    to tell every RE to match case-insensitively -- and, of course, live happily ever after!-)

    0 讨论(0)
提交回复
热议问题