Django中能否构建强制使用查询字符串的URL模式并保留GET参数?
关于Django URL模式匹配查询字符串的问题
首先得明确一个关键事实:Django的URLconf路由系统只匹配URL的路径部分(也就是?之前的内容),完全不会处理?后面的查询字符串。所以你尝试把?filter=(?P<filter>.+?)写在URL正则里的方式是行不通的——Django的路由根本看不到查询字符串这部分内容,那个规则永远不会被匹配到。
那怎么实现你想要的“带查询字符串时匹配另一个视图,同时保留GET参数”的需求呢?其实可以通过视图层的分发逻辑来实现,下面给你两种可行的方案:
方案1:用分发函数视图路由到不同类视图
先定义一个简单的分发函数,检查请求的GET参数,然后转发到对应的类视图:
from django.views.decorators.http import require_GET from yourapp import views @require_GET def cats_view_dispatcher(request): # 检查是否存在filter查询参数 if 'filter' in request.GET: # 转发到过滤后的列表视图 return views.CatsFilteredListView.as_view()(request) else: # 转发到普通列表视图 return views.CatsListView.as_view()(request) # URL配置只需要保留一个路径规则 urlpatterns = [ url(r'^/cats/$', cats_view_dispatcher, name='cats'), ]
方案2:自定义基类视图处理分发
如果更习惯用类视图,可以写一个基类,重写dispatch方法来做路由分发:
from django.views.generic import View from yourapp import views class CatsDispatcherView(View): def dispatch(self, request, *args, **kwargs): if 'filter' in request.GET: # 直接调用过滤视图的as_view()实例 return views.CatsFilteredListView.as_view()(request, *args, **kwargs) # 没有filter参数时走默认逻辑 return super().dispatch(request, *args, **kwargs) # URL配置同样只需要一条规则 urlpatterns = [ url(r'^/cats/$', CatsDispatcherView.as_view(), name='cats'), ]
关于GET参数的保留
不管用哪种方案,request.GET里的查询参数都会完整保留——因为查询字符串是由WSGI服务器解析后传递给Django的,和URL路由匹配完全无关,所以你在CatsFilteredListView里依然可以通过request.GET.get('filter')获取到参数值。
最后再提一句:虽然你说这是测试用例,但实际开发中如果要做过滤,更推荐用路径参数(比如/cats/filter/kittens/)的方式,这样更符合RESTful风格,也更容易通过URLconf直接路由。
内容的提问来源于stack exchange,提问作者Nebulosar
相关产品推荐
相关产品推荐

