Django之URL分发器
URL映射:
视图写完后,要与URL进行映射(即用户在浏览器中输入什么样的url可以请求到这个视图函数),Django会从url.py文件中寻找相对应的视图,这个文件中有个urlpatterns变量,这个变量中通过path函数包含着要请求的视图。为什么会从url.py文件中寻找呢,因为在setting中有个ROOT_URLCONF = 'gjz.urls';所有的URL映射都是从这个项目的url文件中开始。
view.py文件:
from django.http import HttpResponse def index(request): return HttpResponse("ok")
项目的url.py文件:
from django.contrib import admin from django.urls import path,include from front import views urlpatterns = [ path('admin/', admin.site.urls), path("index/",views.index), ]
当我们在浏览器中输入127.0.0.1:8000/index的时候Django会从url.py文件中寻找path函数包含的匹配规则中的index/,并映射到对应的视图。
URL的模块化:一个Django项目是由多个app组成的,如果把每个APP的url映射都放到项目的url文件中显得太多了,不好管理,最好的办法就是把每个APP的映射条件放到自己的APP内,即在自己的APP内添加一个url文件,这个url文件中包含着自己app的映射关系,即url的模块化。
比如有两个APP一个Front,一个CMS模块那么该如何映射呢:
1APP中添加url.py文件
2项目的url.py文件中包含每个app的url.py文件,项目url.py代码如下:
from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path("front/",include("front.urls")), path("cms",include("cms.urls")), ]
3每个APP的url.py代码:
Front中的url.py
from django.urls import path from . import views urlpatterns=[ path("",views.index), ]
cms的url.py
from django.urls import path from . import views app_name = "cms" urlpatterns = [ path("",views.index), ]
当我们在浏览器中输入127.0.0.1:8000/front的时候,Django会从项目的url文件中开始找,找到后再去include包含的url中接着找,然后在返回对应的视图。
path()函数与repath()函数:
path()函数与repath()函数最大的区别就是repath()第一个参数route可以使用正则表达式来实现一些复制的需求。
path()定义为:path(route,view,name=None,kwargs=None);前两个参数是必须的后面两个可以省略
route参数:url的匹配规则。可以传递参数以<>尖括号的形式传递,并且可以指定参数的类型:
<int:id>:匹配热议的零或者正整数
<str:id>:非空的字符串类型
<uuid>:匹配uuid字符串
<path>:非空英文字符串,可以包含斜杠
view参数:视图函数或者类视图函数或者include()函数的返回值
name参数:这个URL的名字
kwargs参数:可以给视图传递一些额外的参数,这个参数是一个字典类型
include()函数:
包含一个APP的url.py文件或者包含一个列表(元组),这个列表(元组)中是path函数(repath())
from django.contrib import admin from django.urls import path,include from cms import views urlpatterns = [ path('admin/', admin.site.urls), path("front/",include("front.urls")), #包含的是一个url文件 path("cms",include([ #包含的是一个path列表 path("", views.index), path("book", views.login) ])), ]
URL中添加参数:
1默认参数:直接在视图中添加一个参数
from django.http import HttpResponse books=[ "三国演义", "水浒传", "西游记", "红楼梦" ] def index(request): return HttpResponse("ok") def book(request,id=1): #不带参数直接访问book则返回 “水浒传” return HttpResponse(books[id])
2查询字符串参数:
def index(request): ID = request.GET.get("id") return HttpResponse(ID)
浏览器中输入:127.0.0.1:8000/front/?id=3;
则返回数字3
查询字符串通过request.GRT.get("字符串名字”)获取;浏览器通过?id=123(?字符串=值)
3传递参数:
(1)path()函数传递参数:path("book/<int:id>"),视图中必须接受这个参数:def index(request,id)
(2) repath()函数传递参数:repath(r"book/(<int:id>)");视图中必须接受这个参数:def index(request,id)
(3)传递参数时,html中的设置:
<ul><li><a href="{% url 'front:book_detail' book.id %}">参数页</a></li> //book_id 为参数;左右留空格</ul>
reverse()函数:在我们实际开发过程中url的名字可能会变动比如登入一开始用login后来变为signin,那么我们在其他地方可能会用到这个名字,这里一旦改变其他的地方也要改变很麻烦,这个时候就会用到name属性给这个url取个别名,然后再反转reverse()得到。
url.py
from django.urls import path from . import views urlpatterns=[ path("index",views.index,name="index"), # path("book/<int:id>",views.book,name="book"), #一开始url的名字是book,后来变为book_list了也不会妨碍重定向 path("book_list/<int:id>",views.book,name="book"), #name=book,给这url去个别名,可以通过这个别名来找到这个url ]
views.py
from django.http import HttpResponse from django.shortcuts import redirect,reverse books=[ "三国演义", "水浒传", "西游记", "红楼梦" ] def index(request): return redirect(reverse("book",kwargs={"id":3})) #带关键字的反转 def book(request,id=1): return HttpResponse(books[id])
应用命名空间与实例命名空间:
应用命名空间:是给这个app取个名字;作用:每个APP可能会有相同url的名字,比如前台和后台都有登入的界面login,那么当我们输入login是去前台的界面呢还是后台的界面呢?这个时候就需要指定app的名字了。
from django.urls import path from . import views app_name = "cms" #给这个APP取个名字叫做cms urlpatterns = [ path("",views.index), path("login/",views.login), path("book<int:id>/",views.book), ]
from django.http import HttpResponse from django.shortcuts import redirect,reverse books=[ "三国演义", "水浒传", "西游记", "红楼梦" ] def index(request): return redirect(reverse("cms:book",kwargs={"id":3})) #当我们要跳转到cms中的book界面的时候用cms:book方式
实例命名空间:一个app可以创建多个实例,即多个url映射同一个app,这样在做反转的时候容易混乱。这个时候就需要实例命名空间了,只需要在include函数中传递一个namespace变量即可。
""" from django.contrib import admin from django.urls import path,include from cms import views urlpatterns = [ path("front1/",include("front.urls",namespace="front1")), path("front2/",include("front.urls",namespace="front2"),), #front1和front2同时映射到了front.urls模块,为了区分他们使用实例命名空间 ]
views.py
from django.http import HttpResponse from django.shortcuts import redirect,reverse def index(request): current_app = request.resolver_match.namespace #获取当前实例命名空间的名字 return redirect(reverse("%s:book" %current_app,kwargs={"id":2})) #使用这个url来找到book def book(request,id): return HttpResponse("book")
自定义URL转换器: