django学习_路由
django2
路由控制器
Route路由,是一种映射关系。路由是把客户端请求的url路径和用户请求的应用程序,这里意指django里面的视图进行绑定映射的一种关系。
请求路径和视图函数不是一一对应的关系
在django中所有的路由最终都被保存到一个叫urlpatterns
的文件里,并且该文件必须在主应用下的urls.py
里进行声明,这是由setting文件决定的
在django运行中,当客户端发送了一个http请求到服务端,服务端的web服务器则会从http协议中提取url地址, 从程序内部找到项目中添加到urlpatterns里面的所有路由信息的url进行遍历匹配。如果相等或者匹配成功,则调用当前url对象的视图方法。
(1)include基本使用
其实在于项目名同名的app文件下的urls.py里有提供一段路由的使用,第三个使用的就是include函数
具体使用方法就是首先要导入这个模块和路由
from django.urls import include, path, re_path
urlpatterns = [
path("ZJR/",include("ReginaApp.urls"))
]
ReginaApp.urls
这个文件是不存在的,所以直接手动创建一个
from django.urls import path, include
from django.shortcuts import HttpResponse
from ReginaApp import views
urlpatterns = [
path("regina/",views.get_ZJR)
]
这样做的目的就在于我们可以把路由分级,不需要把所有的路由函数都堆在同一个目录下面,当我们再访问127.0.0.1:8090时,此时是报错的,因为总路由里面没有根目录这个东西,如果想访问到get_ZJR这个视图函数,url需要加上ZJR/regina
(2)re_path基本使用
re_path和path的作用是一样的。只不过”re_path”是在写url的时候可以用正则表达式,功能更加强大
写正则表达式都推荐使用原生字符串。也就是以‘r’开头的字符串
在正则表达式中定义变量,需要使用圆括号括起来。这个参数是有名字的,那么需要使用”?P<参数的名字>”。然后在后面添加正则表达式的规则。
Eg:
(一)固定输出
在选择某个月的日历的时候,输入年月会相应的返回当时的文章
#djangoRegina.urls:
path("1999-12",views.article)
# reginaApp.views:
def article(request):
return HttpResponse("1999-12 文章")
那如果我要挑选的选项很多,path就会有非常多的路由要一一列举,所以这样做就很繁琐。
(二)加入正则
d
表示数字,我们将原来的路由改为
re_path("article/d{4}/d{2}/",views.article)
但是这样做,多月两位数月份就合理,一位数月份就会报错
所以再把格式修改一下re_path("article/d{4}/d{1,2}/",views.article)
(三)匹配参数
上图得知,我需要根据url里得到的年份去匹配文章,所以在路由中就要进行分组
re_path("article/(d{4})/(d{1,2})/",views.article)
def article(request,year,month):
return HttpResponse("{}-{} 文章".format(year,month))
(四)覆盖
re_path("regina/(d{4})/",views.articleByYear),
re_path("regina/(d{4})/(d{1,2})/",views.articleByMonth)
在拥有相同的路由的时候,更短的路由具有更高的优先级
def articleByYear(request,year):
return HttpResponse("{}文章".format(year))
def articleByMonth(request,year,month):
return HttpResponse("{}-{}文章".format(year,month))
如果想要区分开路由,则需要添加(符号`re_path(“regina/(d{4})/)”,views.articleByYear),`
(五)有名分组
顾名思义想给我选定的分组起个名字,如果在不起名字的时候,视图函数的参数顺序是必须要固定的,乱序则会影响功能。所以给起个名字
re_path("regina/(?P<year>d{4})/(?P<month>d{1,2})/",views.articleByMonth)
def articleByMonth(request,month,year):
return HttpResponse("{}-{}文章".format(year,month))
(3)路由转发器
首先要在app下导入from django.urls import register_converter
#APP.urls
from django.urls import register_converter
class MobileConvert():
regex = "1[3-9]d{9}"
def to_python(self,value):
print(type(value))
# 将匹配结果传递到视图内部时使用
# 返回str还是int主要看需求,纯数字的可以返回int
return value
# register_converter(路由转换器的类名,调用别名)
register_converter(MobileConvert,"mobile")
urlpatterns = [
path("regina/",views.get_ZJR),
path("<mobile:number>",views.ZJrui) 这里的mobile要和注册时起的名字一致
#APP.views 这里的number要和路由中命名的名字一致
def ZJrui(request,number):
return HttpResponse("HI,{}用户".format(number))
(4)反向解析
这样做的好处就是可以把每一个正则规则放到子app下面
在使用Django 项目时,一个常见的需求是获得URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。人们强烈希望不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。
在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:
- 在模板中:使用url模板标签
- 在Python 代码中:使用from django.urls import reverse 函数。
urls.py中为url设置别名参数:
from django.conf.urls import url
from . import views
urlpatterns = [
#...
url(r"^articles/([0-9]{4})/$", views.year_archive, name="news-year-archive"),
#...
]
应用之在模板中反向解析:
<a href="{% url "news-year-archive" 2012 %}">2012 Archive</a>
<a href="/articles/2012/">2012 Archive</a>
应用之在py文本中反向解析:
from django.shortcuts import redirect
from django.urls import reverse
def redirect_to_year(request):
year = 2006
reverse_path=reverse("news-year-archive", args=(year,))
return redirect(reverse_path) # 等效 redirect("/articles/2006/")