如何实现Django的URL路径不区分大小写?
问题解决:URL大小写导致的404及两种需求实现
问题原因
你遇到的404是因为slugify()生成的slug是全小写格式(比如"PayPal"会被转为"paypal"存入数据库),而DetailView默认对slug字段做精确匹配,URL中传入的"PayPal"与数据库里的"paypal"不匹配,因此找不到对应记录。
方案一:URL大小写不敏感访问
重写ProcessorDetailView的get_object方法,将传入的slug转为小写后再查询数据库,无论URL是大写、小写还是混合大小写,都能匹配到正确记录:
from django.http import Http404 class ProcessorDetailView(DetailView): model = Processor template_name = 'finder/processor_detail.html' slug_field = 'slug' slug_url_kwarg = 'slug' def get_object(self, queryset=None): # 获取URL中的slug并转为小写 slug = self.kwargs.get(self.slug_url_kwarg).lower() if queryset is None: queryset = self.get_queryset() # 用小写slug过滤查询集 queryset = queryset.filter(slug=slug) try: obj = queryset.get() except queryset.model.DoesNotExist: raise Http404(f"No {queryset.model._meta.verbose_name} found matching the query") return obj
方案二:自动将URL转为全小写并跳转
通过重写dispatch方法,判断URL中的slug是否为全小写,若不是则重定向到全小写的URL,同时保证页面正常访问:
from django.shortcuts import redirect class ProcessorDetailView(DetailView): model = Processor template_name = 'finder/processor_detail.html' slug_field = 'slug' slug_url_kwarg = 'slug' def dispatch(self, request, *args, **kwargs): slug = kwargs.get(self.slug_url_kwarg) # 检查slug是否为全小写,否则重定向 if slug != slug.lower(): kwargs[self.slug_url_kwarg] = slug.lower() return redirect(request.path.lower()) return super().dispatch(request, *args, **kwargs)
额外说明
你的save方法已经通过slugify()确保数据库中的slug都是全小写,所以无需担心数据不一致问题。如果存在旧数据slug不是小写的情况,可以通过以下命令批量更新:
# 在Django shell中执行 from django.utils.text import slugify from your_app.models import Processor for processor in Processor.objects.all(): if processor.slug != slugify(processor.name): processor.slug = slugify(processor.name) processor.save()
内容的提问来源于stack exchange,提问作者tthheemmaannii
相关产品推荐
相关产品推荐

