Django笔记:URL映射

python

本文主要记了一些Django中URL映射相关的知识点,包括URL映射关系配置、URL传参、URL反转等,本文为学习笔记,仅供参考。

一、URL映射关系配置

URL映射关系默认是配置在主app下urls.py中的urlpatterns列表中,如果想要自己指定配置映射关系所在文件,只需要修改主app中settings.py文件中的ROOT_URLCONF配置项即可,但是urlpatterns这个变量是固定的,无法修改,所以修改ROOT_URLCONF配置项之后,Django就会到你指定的文件中查找urlpatterns变量,并根据这个列表中的映射关系来进行URL的映射。
urlpatterns列表中的元素是一个经过pathre_path函数包装后的结果,这两个函数都在django.urls中,直接导入使用即可。这两个函数的用法都是相似的,不同之处在于,re_pathroute参数(即URL)需要使用正则表达式,如果对URL没有特殊要求的话,建议尽量使用path就可以了。
path函数常见用法有两种:

  • 一种是直接传入URL字符串和对应视图函数两个参数即可,例如path("article/page/2/", views.page_detail),第一个route参数为URL字符串,第二个view参数为URL对应的视图函数。通常情况下两个参数已经够用了,但是如果想要给这个URL命令,以便用于URL的反转,可以指定name参数。
  • 另一种是指定子app的URL前缀以及使用include函数包装的子appurls.py路径,例如path("articel/", include("article.urls")),第一个route参数只需要指定子app的URL前缀,不需要给出完整的URL字符串,第二个view参数为通过django.urls.include包装后的子appurls.py路径。这种用法涉及到URL的分层管理,可以参考后面“URL分层管理”小节。

二、URL传参

1、URL查询字符串

URL中查询字符串的参数直接使用视图函数的第一个参数request.GET进行获取即可,查询字符串通常是通过GET方式发送的请求,所以查询字符串的信息可以在request.GET中得到,而这个变量是一个类似字典的数据结构,直接使用它的get方法进行获取即可。
示例:访问http://127.0.0.1:8000/book/author/?id=3,对应的视图函数如下

def author_detail(request):

author_id = request.GET.get("id")

text = "作者的ID是:{}".format(author_id)

return HttpResponse(text)

2、URL参数传递

如果想要URL字符串中的某部分变成参数传递给视图函数,可以在指定URL字符串时使用尖括号<param_name>将对应参数括起来,并在视图函数中定义相同名称的参数即可。当然,也可以在URL字符串中定义多个参数,只需要在视图函数中按顺序定义同样的参数来接收即可。
注:可以给视图函数的参数指定默认值,访问时如果URL中没有传入该参数则会使用该参数的默认值。

"""视图函数代码"""

from django.http import HttpResponse

def book(request):

return HttpResponse("图书首页!")

# 注意此处的book_id必须与URL中的参数<book_id>是相同的

def book_detail(request, book_id):

text = "你获取的图书id是:{}".format(book_id)

return HttpResponse(text)

"""URL映射关系配置代码"""

urlpatterns = [

path("admin/", admin.site.urls),

path("book/", book),

path("book/detail/<book_id>/", book_detail)

]

注:使用re_path时,传参使用正则表达式的分组命名方式,即(?P<param_name>),这个参数名与视图函数的参数名也是一一对应的。

3、使用URL类型转换器指定参数类型

URL字符串中传递给视图函数的参数默认都是字符串类型的,即使用的是默认的URL类型转换器str,如果想要给参数指定为别的类型,如int类型,则需要使用形如<int:book_id>来进行参数类型指定。注意,如果指定了URL类型,那么在视图函数中拿到的该参数也是对应的数据类型,例如指定了参数为int类型,不仅URL字符串中该部分必须满足int类型要求,而且视图函数中该参数拿到后也是Python中对应的int类型。

Django中有一些内置的URL类型转换器,都在from django.urls import converters中,可自行查看,常用的有以下几种:

  • int:必须是0到9之间的一个或多个数字。

  • str:除了斜杠/之外的一个或多个任意字符。(也是默认的参数类型)

  • uuid:一个uuid字符串,可以使用Python内置库方法来生成import uuid;uuid.uuid4()

  • slug:满足正则[-a-zA-Z0-9_]+的所有字符串。

  • path:一个或多个任意字符(斜杠/也可以)。

4、自定义URL类型转换器

自定义URL类型转换器其实也是根据内置的转换器写法来进行自定义的,可以参考from django.urls import converters中内置转换器的源码,一个自定义的url类型转换器通常分为三部分:regex正则表达式(转换规则)、to_python函数(将url中的参数处理之后再传入视图函数)和to_url函数(将参数处理之后再拼接到url之中)。定义好转换器之后,需要使用from django.urls import register_converter将转换器注册到Django中。

示例代码如下:

"""直接定义在urls.py中"""

from django.urls import path

from . import views

from django.urls import register_converter

# 自定义URL类型转换器:将URL中类似python+django+flask的字符串

# 转换为以+分隔的列表传入视图函数中,反转为URL时再以+拼接到URL中

class CategoryConverter:

regex = r"w+|w+(+w+)+"

def to_python(self, value):

# 此方法是将url中的参数处理之后再传入对应的视图函数中

# value:python+django+flask

return value.split("+")

def to_url(self, value):

# 此方法是将在reverse反转时给url传入的参数处理之后再放入url中,形成最终的url

# value:["python", "django", "flask"]

return "+".join(value)

# 注册自定义的转换器

register_converter(CategoryConverter, "cate")

urlpatterns = [

path("", views.article),

# 使用自定义的转换器

path("list/<cate:categories>/", views.article_list, name="list")

]

"""views.py"""

def article_list(request, categories):

# 如果访问:http://127.0.0.1:8000/article/list/python+django+flask/

# 打印结果为:/article/list/python+django+flask/

print(reverse("list", kwargs={"categories": categories}))

text = "文章分类是:{}".format(categories)

return HttpResponse(text)

注:url转换器定义的文件一定要在运行时得到执行,不然无法进行注册,可以放在urls.py中,也可以将定义转换器的文件在包的__init__.py文件中进行导入。

三、URL分层管理

当新建的app较多时,不宜将所有的URL映射都放在主app(该app通常与项目同名)的urls.py文件中,就像app下的views.pymodels.py等文件(使用命令窗口的命令创建app时,会自动生成这些文件),用专门的文件来管理各自的功能,推荐在app下新建一个urls.py文件,用来专门管理当前app的所有URL映射关系,这样也方便开发人员的维护和管理。

URL的分层管理需要注意以下两点:

  • 在子app下新建一个urls.py(文件名称可以自己取,但是通常就命名为urls.py即可,方便辨认),然后在里面同样定义一个urlpatterns变量。注意,这个urlpatterns中的URL字符串不用再添加子app对应的URL前缀了。
  • 在主app的urls.pyurlpatterns变量中添加一个URL映射,第一个参数为子app的URL前缀,第二个参数为from django.urls import include包装的子app对应的urls.py文件路径(此路径为相对于项目根目录的相对路径)。

"""主app的urls.py文件内容"""

from django.contrib import admin

from django.urls import path, include

urlpatterns = [

path("admin/", admin.site.urls),

# 这里只需要添加app的url前缀和对应urlpattterns变量所在文件的路径即可

path("book/", include("book.urls"))

]

"""子app“book”目录中的urls.py文件内容"""

from django.urls import path

from .views import book, book_detail

# 这里不用再添加app的url前缀了

urlpatterns = [

path("", book),

path("detail/<book_id>/", book_detail)

]

四、URL反转

URL反转表示根据一个名称就可以得到对应的完整URL字符串,而不用自己每次手动编写完整的URL,如果项目中许多地方都会用到某个URL,就可以考虑使用URL反转了,URL反转需要用到from django.shortcuts import reverse,基本用法为:使用形如reverse(url_name)即可得到对应的URL。

1、URL命名

想要给URL命名,在配置URL映射关系时,给path函数指定name参数即可,然后使用reverse(url_name)函数反转就可以得到对应名称的URL了。

"""配置URL映射关系"""

from django.urls import path

from hello_world import views

urlpatterns = [

# 使用name参数给当前URL指定名称

path("index/", views.index, name="index")

]

"""视图函数定义"""

from django.shortcuts import render, reverse

def index(request):

# 获取名称为index的URL,打印结果为:/index/

print(reverse("index"))

return render(request, "index.html")

2、app应用命名空间和实例命名空间

配置app应用命名空间是为了规避产生同名URL的情况,app应用命令空间的配置是直接在对应app目录的urls.py中定义一个app_name=xxx的变量即可,反转时加上对应的app_name即可,如reverse("app_name:url_name")

from django.urls import path

from . import views

# 配置app应用命令空间

app_name = "front"

urlpatterns = [

path("", views.index),

# 给URL指定名称

path("login/", views.login, name="login"),

]

from django.http import HttpResponse

from django.shortcuts import redirect, reverse

def index(request):

username = request.GET.get("username")

if username:

return HttpResponse("前台 首页!")

else:

# 反转时使用“app应用命名空间:url名称”的格式

return redirect(reverse("front:login"))

使用实例命名空间是为了规避不同的URL映射到了相同的urls.py中,即不同的实例映射到了同一个app上,此时反转得到的URL可能就不是我们想要的了。实例命名空间配置是在主app中配置子app的URL前缀时的include中指定其namespace参数,然后再使用request.resolver_match.namespace获取当前实例命名空间即可,此时就不再使用应用命名空间了(虽然配置了)。注意,指定实例命名空间时必须同时指定应用命名空间,单独指定实例命名空间是不可以的,程序会报错。

from django.contrib import admin

from django.urls import path, include

urlpatterns = [

path("admin/", admin.site.urls),

# 在include中指定namespace命名空间

# 不同的前缀指向了相同的urls.py文件,所以只用app应用空间是不够的

# 需要再指定namespace命名空间,即实例命名空间

path("cms1/", include("cms.urls", namespace="cms1")),

path("cms2/", include("cms.urls", namespace="cms2")),

path("", include("front.urls"))

]

from django.http import HttpResponse

from django.shortcuts import redirect, reverse

def index(request):

username = request.GET.get("username")

if username:

return HttpResponse("cms 首页!")

else:

# 获取当前所处的实例命名空间

current_namespace = request.resolver_match.namespace

return redirect(reverse("{}:login".format(current_namespace)))

五、其他函数

1、django.urls.include

include有三种用法:include(module, namespace=None)include((pattern_list, app_namespace), namespace=Noneinclude(pattern_list),它们的参数使用如下:

  • module:子URL的模块字符串(即对应app的urls.py文件路径)。

  • namespace:实例命名空间。需要注意的是,指定实例命名空间时,需要同时指定对应的app应用命名空间(在对应app的urls.py中配置变量app_name)。

  • pattern_list:一个子URL的模块字符串或者path对象的列表,后者相当于是在path的第一个参数指定了子app的URL前缀,如果这个子app下有多个URL,就可以直接放在这个pattern_list列表中。

  • app_namespace:应用命名空间。注意,应用命名空间既可以在include中指定,也可以通过在子app的urls.py中配置app_name的方式来指定。

  • namespace:实例命名空间。

2、django.shortcuts.reverse

reverse用于url的反转,通常只需要在path中指定name参数即可(必要的时候也可以指定app应用命名空间或实例命名空间)。如果url中含有参数,则需要在使用reverse时传入kwargs参数,以字典的形式将参数传入。
注:如果是查询字符串的参数,则需要reverse反转之后自己手动进行拼接url字符串。

"""视图函数"""

from django.http import HttpResponse

from django.shortcuts import reverse, redirect

def index(request):

username = request.GET.get("username")

if username:

return HttpResponse("首页")

else:

# detail对应的url映射为:path("detail/<article_id>/", article_detail, name="detail"),

detail_url = reverse("detail", kwargs={"article_id": 333})

# 如果需要传入查询字符串,则需要自己手动进行拼接,如:detail_url += "?username=xxx"

return redirect(detail_url)

def article_detail(request, article_id):

text = "文章的id是:{}".format(article_id)

return HttpResponse(text)

以上是 Django笔记:URL映射 的全部内容, 来源链接: utcz.com/z/531147.html

回到顶部