第一章 django安装与介绍
第二章 django基础使用
上一篇文章《django基础使用》,大致演示了基础的django使用方法,接下来的内容将会详细的对路由层进行学习。但在学习之前需要了解django的请求生命周期流程图。
路由匹配的特点是:
django路由匹配再对/xxx没有匹配关系时,会在末尾加上一个斜杠再次匹配
例如:
url(r'^index/', views.index)
针对上面的路由配置,跳转到127.0.0.1/index,第一次匹配不到,会再次发送请求 127.0.0.1/index/ 此时就会配对上,然后根据视图函数返回响应。
这种二次匹配加斜杠的方式可以通过配置来关闭
APPEND_SLASH = False
由于url第一个参数是正则 所以当项目特别大 对应关系特别多的时候要格外的注意是否会出现路由顶替的现象
设置不再url后携带后缀时自动跳转(多用于跳转主页):
url(r"^$", views.index)
也可以定义一个尾页 用户输入一个没有对应关系的直接返回
url("^.*", views.error)
这样匹配不到关系会自动调用error视图函数,但这样会让一些不应该显示error页面的url也显示项目的error页面,所以不推荐使用。
注意:
路由设置中第一个参数为正则表达式,所以当路由多了之后容易造成一些跳转问题,例如:
127.0.0.1/index/ 对应主页
127.0.0.1/indexasdasdasdasd/ 也会对应到主页,但这样是不符合预期的,所有会使用$对正则进行结尾的限制。
在用户输入url后,自动匹配关系,然后将设定的部分url作为参数传给视图函数。
无名分组为正则参数中不设置参数名,此时传给视图函数的参数为位置参数。
无名分组路由中的设置方式:
url("^passage/all/(\d*)/$", views.passage) # ()的设置可以是多个
#在无名分组中按照位置传递,第一个传递的为request
此时除了向视图函数传递request以外还传递了一个数字,这个数字表示了第几页。
无名分组视图层中函数的接收方式:
def passage(request, pagination): # 此时pagination中就是对应的页码
#此时为接收一个参数,也可以书写多个形参接收
.......
#当我们不知道要接收几个参数时可以使用*args来接收
def passage(request, *args):
......
在用户输入url后,自动匹配关系,然后将设定的部分url作为参数传给视图函数。
有名分组为正则参数中为传递的值设置参数名,此时传给视图函数的参数为关键字参数。
有名分组路由中的设置方式:
url("^passage/all/(?P\d*)/$" , views.passage) # ()的设置可以是多个
#在有名分组中按照位置传递,第一个传递的为request,后续参数为关键字参数
此时除了向视图函数传递request以外还传递了一个参数,这个参数表示了第几页。
有名分组视图层中函数的接收方式:
def passage(request, pagination): # 此时pagination中就是对应的页码,此处必须和路由中设置的名字一致
#此时为接收一个参数,也可以书写多个形参接收
.......
#当我们不知道要接收几个参数时可以使用**kwargs来接收
def passage(request, **kwargs):
......
页面上有很多a标签链接了其他路由
路由匹配表达式出现了变化,html页面上的地址全部失效
这个时候可以使用反向解析获取对应的路由
1.在路由层中为指定路由设置name
url(r'^lo/', views.login, name="login_view"),
url(r'^re/', views.register, name="register_view"),
2.在视图层为对应视图函数绑定reverse
from django.shortcuts import reverse
def login(request):
reverse('login_view')
def register(request):
reverse('register_view')
3.在对应需要使用路由的前端设置
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这是主页title>
head>
<body>
<a href="{% url 'login_view' %}">登录页面a>
<a href="{% url 'register_view' %}">注册页面a>
body>
html>
1.在路由层中为指定路由设置name
url(r"^not/(\d*)/$", views.not_grouping, name="not_view"),
2.在视图层为对应视图函数绑定reverse
from django.shortcuts import reverse
def not_grouping(request, num):
reverse("not_view", args=(45,))
return HttpResponse("无名分组参数已发送")
3.在对应需要使用路由的前端设置
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这是主页title>
head>
<body>
<a href="{% url 'not_view' 45 %}">文章页面,无名分组,反向解析a>
<a href="{% url 'not_view' 45 %}">文章页面,无名分组,反向解析a>
body>
html>
1.在路由层中为指定路由设置name
url(r"^has/(?P\d*)/$" , views.has_grouping, name="has_view"),
2.在视图层为对应视图函数绑定reverse
from django.shortcuts import reverse
def has_grouping(request, num):
reverse("has_view", args=(65,)) # 绑定方式1 当前端调用反向解析直接传入参数值使用 args来绑定
reverse("has_view", kwargs={"num":65}) # 绑定方式2 当前端调用反向解析通过关键字参数传入时 使用kwargs来绑定
#俩种绑定方式在同一个视图函数中只能选一种
return HttpResponse("有名分组参数已发送")
3.在对应需要使用路由的前端设置
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这是主页title>
head>
<body>
<a href="{% url 'has_view' 65 %}">文章页面,有名分组方式1,反向解a>
<a href="{% url 'has_view' 65 %}">文章页面,有名分组方式1,反向解a>
{# 上方的方式一,对应reverse按照顺序参数传值时使用#}
<a href="{% url 'has_view' num=65 %}">文章页面,有名分组方式2,反向a>
<a href="{% url 'has_view' num=65 %}">文章页面,有名分组方式2,反向解a>
{# 上方的方式二,对应reverse按照关键字参数传值时使用,特别注意关键字参数编写时不能带上空格#}
body>
html>
当一个项目特别大时,开发完毕后的路由会非常的大,管理和维护也困难,此时可以将整个项目拆解为多个app容器来各自开发,此时项目文件下的urls.py只需要集成各个app容器的路由即可。
1.在每个app容器中创建自己的urls(最好在各自app容器下创建templates、static)
2.对应每个app容器下的路由与视图的编写
3.在项目同名文件中的路由中集成所有app容器中的路由
第一种集成方式,通过导入所有app下的路由,其中传参使用include:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls)),
]
第二种集成方式,直接使用注册好的app直接引入路由
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls')),
]
当多个app容器中有相同名字的路由被配置时,使用反向解析,路由分发不会分辨其app容器,而是直接使用相同名字中最后一个加载的配置作为解析结果。此时可以使用俩种方式解决该问题。
方法一:
1.在总路由(总路由指项目同名文件下的urls.py)中设置名称空间
url(r'^app01/',include('app01.urls', namespace="app01")),
url(r'^app02/',include('app02.urls', namespace="app02")),
2.在对应app容器对应的路由中设置name
# app01容器下的urls
url(r"^index/", views.index, name="index_view"),
# app02容器下的urls
url(r"^index/", views.index, name="index_view"),
3.在对应需要的视图函数中设置reverse
# app01容器下的views
def index(request):
reverse("app01:index_view")
return render(request, "index.html")
# app02容器下的views
def index(request):
reverse("app02:index_view")
return render(request, "index1.html")
4.在对应需要使用到反向解析结果的地方使用
<a href="{% url 'app01:login_view' %}">登录页面,反向解析a>
<a href="{% url 'app01:register_view' %}">注册页面,反向解析a>
<a href="{% url 'app01:not_view' 45 %}">文章页面,无名分组,反向解析a>
<a href="{% url 'app01:not_view' 45 %}">文章页面,无名分组,反向解析a>
<a href="{% url 'app01:has_view' 65 %}">文章页面,有名分组方式1,反向解析a>
<a href="{% url 'app01:has_view' 65 %}">文章页面,有名分组方式1,反向解析a>
<a href="{% url 'app01:has_view' num=65 %}">文章页面,有名分组方式2,反向解析a>
<a href="{% url 'app01:has_view' num=65 %}">文章页面,有名分组方式2,反向解析a>
方式二:
只需要确保反向解析的别名在整个项目中不重复即可
可以在别名的前面加上应用名的前缀
# app01容器下的urls
url(r"^index/", views.index, name="app01_index_view"),
# app02容器下的urls
url(r"^index/", views.index, name="app02_index_view"),