Нечувствительные к регистру URL-адреса для Django?
Кажется, что по умолчанию django url solver выполняет поиск с учетом регистра для решения url и различает "/Login" и "login". Мои шаблоны 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),
)
Может ли кто-нибудь, пожалуйста, направить меня, как сделать регистр django urls нечувствительным?
Ответы
Ответ 1
Просто поместите (?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),
)
чтобы рассказать каждому RE, чтобы он не зависел от случая, - и, конечно же, жить долго и счастливо! -)
Ответ 2
В 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') ]
поднимает
ValueError: Non-reversible reg-exp portion: '(?i'
но работает с регулярным выражением r'home/$(?i)'
.
Ответ 3
В Django 2.0 (выпущенном в декабре 2017 года) рекомендуемый способ использования регулярных выражений для сопоставления 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),
]
Ответ 4
Вы также можете управлять этим с вашей точки зрения. Например, если у вас есть generic.DetailView, вы можете переопределить метод get_queryset и установить значение slug в нижний регистр:
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'),