django路由参数可以为空吗?

path(r'category/<slug:title>/', (views.CategorysTagView.as_view(), name='category'),

上述URL中的title可以默认为空吗,例如可传可不传!

阅读 3.7k
2 个回答

不可以。

str - 匹配除了 '/' 之外的非空字符串。如果表达式内不包含转换器,则会默认匹配字符串。

来自:https://docs.djangoproject.com/zh-hans/4.2/topics/http/urls/#...


更新 1:

查看示例仓库:https://jihulab.com/zhoushengdao-sf/django-route

如果像这样一个路径:url/<arg1>/<arg2>/,如果参数可以为空的话,那么有以下四种情况:

  1. <arg2> 为空的话,那么 url 就是 url/<arg1>/,(经过测试,多个连续的斜杠会被视为一个);
  2. <arg1> 为空的话,那么 url 就是 url/<arg2>/
  3. <arg1><arg2> 都为空,那么 url 就是 url/
  4. <arg1><arg2> 都不为空,那么 url 就是 url/<arg1>/<arg2>/

对于这四种情况,你每个都需要声明一个路由:

urlpatterns = [
    path("url/<arg1>/", views.args),          # 第一种情况
    path("url/<arg2>/", views.args),          # 第二种情况
    path("url/", views.args),                 # 第三种情况
    path("url/<arg1>/<arg2>/", views.args)    # 第四种情况
]

但是 Django 在遇到请求时按顺序遍历每个 URL 模式,然后会在所请求的URL匹配到第一个模式后停止文档),所以按照上面的定义,第二种情况永远不会触发,而如果交换一下,那么第一种情况不会触发。

当然,如果你能很方便的区分开传入视图的参数是 arg1 还是 arg2,第一二种情况你可以合并为一条路由 path("url/<arg>/", views.args),然后在视图函数中这样写:

def args(request, arg=None, arg1=None, arg2=None):
    print(arg, arg1, arg2)
    if arg in arg1_list and arg1 is None and arg2 is None:
        return HttpResponse("第一种情况")
    if arg in arg2_list and arg1 is None and arg2 is None:
        return HttpResponse("第二种情况")
    if arg is None and arg1 is None and arg2 is None:
        return HttpResponse("第三种情况")
    if arg is None and arg1 is not None and arg2 is not None:
        return HttpResponse("第四种情况")

其中 arg1_listarg2_list 分别是 arg1arg2 的所有可能的值的列表。

你题目中描述的方式, title 不能为空,否则路由无法匹配。
如果你想让这个参数可选, 那你可以再多声明一个路由,把你要不选的部分给省略掉, 然后视图函数那里的参数默认为 None

比如:

# urls.py
urlpatterns = [
    path("category/", views.CategoryTagView.as_view(), name="category"),
    re_path(r"^category/(?P<title>[\w-]+)/", views.CategoryTagView.as_view(), name="category"),
]

# views.py
class CategoryTagView(View):
    @staticmethod
    def get(request: HttpRequest, title: Optional[str] = None):
        if title:
            return HttpResponse(f"Received title: {title}")

        return HttpResponse("Received title: None")
curl http://127.0.0.1:8000/category/
## Received title: None

curl http://127.0.0.1:8000/category/ab-c-d/
## Received title: ab-c-d
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题