python Django的不区分大小写的网址?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1515634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 22:27:39  来源:igfitidea点击:

Case insensitive urls for Django?

pythondjango

提问by Software Enthusiastic

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.

似乎默认情况下 django 的 url 解算器执行区分大小写的搜索来解决 url 并区分“/登录”和“登录”。我的网址模式如下。

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

Can anyone please guide me, how to make django urls case insensitive?

任何人都可以指导我,如何使 django url 不区分大小写?

回答by Alex Martelli

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

只需放在(?i)每个r'...'字符串的开头,即:

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

告诉每个 RE 不区分大小写匹配——当然,从此过上幸福的生活!-)

回答by notsofast

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

在 Django 2.1 中,似乎(?i)放置在 URL 正则表达式中的任何位置都会导致它忽略大小写。但是,reverse()除非在正则表达式的末尾(?i)跟随,否则会失败$

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

但使用正则表达式干净地运行r'home/$(?i)'

回答by chrki

With Django 2.0 (released in December 2017) the recommended way to use regular expressions for URL-matching is now re_pathinstead of url:

在 Django 2.0(2017 年 12 月发布)中,使用正则表达式进行 URL 匹配的推荐方法现在re_path改为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),
]

回答by Sym

Django 2.2 update

Django 2.2 更新

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

对正则表达式组((?i)、(?L)、(?m)、(?s) 和 (?u))中的内联标志的支持在 Django 1.11 中被弃用,并在 Django 2.1 中被移除

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

在 Django 2.2 中,添加(?i)到模式的开头会产生以下异常:

ValueError: Non-reversible reg-exp portion

ValueError: Non-reversible reg-exp portion

confusingly, adding it to the end produces this warning:

令人困惑的是,将其添加到末尾会产生以下警告:

DeprecationWarning: Flags not at the start of the expression

DeprecationWarning: Flags not at the start of the expression

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

在 Django 中处理不区分大小写的 URL的新建议方法是使用自定义 404 处理程序

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

FWIW,那张票还表明“不区分大小写的 URL 不是一个好习惯”,但是它没有为此提供更多的争论。

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

PyPi 上有一个包django-icase,看起来是个不错的选择

回答by Danut Popa

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

你也可以从你的角度管理这个。例如,如果您有一个 generic.DetailView,您可以覆盖get_queryset方法并将slug值设置为小写:

models.py:

模型.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:

视图.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:

网址.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'),