一、匹配规则 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test',views.test), url(r'testadd',views.testadd), ] 当在浏览器页面的url里输入 'testadd' 时,不会出现testadd函数所对应的结果,而是出现test函数对应的结果。即路由一旦匹配就不再走下面的路由匹配关系了。 解决方式,在后面加上反斜杠/ 即可解决。 路由层增加首页的方式: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test/',views.test), url(r'testadd/',views.testadd), url(r'^$',view.home) ] 即在浏览器页面只输入路径的时候,会出现home函数所对应的html页面。以^开头,以$结尾,实际上啥也没输入。 路由层增加尾页的方式:(当所有路径都匹配不上时,返回404信息) urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test/',views.test), url(r'testadd/',views.testadd), url(r'^$',view.home), url(r'',view.error) ] 自己定义一个html页面,展示给用户看,错误信息404
二、分组 无名分组: url(r'^test/([0-9]{4})/',views.test) 会将加了括号的正则表达式匹配的内容当做位置参数传递给后面的视图函数 例如: 1、现在路由层写好对应关系 url(r'^test/([0-9]{4})/',views.test) 2、视图层 def test(request,haha): #必须存在一个位置形参接收路由的数据 print(haha) return HttpResponse('ok') 3、流量器输入路由 127.0.0.1:8000/2345 结果:haha 打印的结果为 2345 小点;如果关系为 url(r'^test/([0-9]{4})',views.test) 即没加尾部的反斜杠时, 路由输入时可以输入多个数字,虽然结果只取4为,这由正则表达式决定。 有名分组: url(r'^test1/(?P<year>d+)/',views.test1) 会将加了括号的正则表达式匹配的内容当做关键字参数传递给后面的视图函数 关键字就是你尖括号里面的名字(year) 视图层: def test1(request,year): #必须是关键字参数去接收 print(year) return HttpResponse('ok') 浏览器输入路由:127.0.0.1:8000/test1/1234567 结果: year的打印结果为 1234567 有名分组和无名分组不能混合使用! 但二者支持多个相同类型的传参
三、反向解析 (根据名字动态获取到对应路径)#注:此时用到的是django2.0版本,url与re_path 等同!
1、路由层 re_path('test311/',views.test3,name='test') #特定写法,name='XXX' 2、视图层 from django.shortcuts import reverse def test3(request): print(reverse('test')) #特定写法 reserver(' name所对应的值') return HttpResponse('ok') 3、浏览器输入 127.0.0.1:8000/test311 结果: 打印的值为/test311/ re_path('test311/',views.test3,name='test') # 可以给每一个路由与视图函数对应关系起一个名字 # 这个名字能够唯一标识出对应的路径 # 注意这个名字不能重复,必须是唯一的
正常的逻辑:
前端使用:可通过a标签的src去实现
{% url 'index' %}
{ % url '你给路由与视图函数对应关系起的别名' %}
后端使用
reverse('index')
reverse('你给路由与视图函数对应关系起的别名')
四、无名分组反向解析 简单验证: from django.shortcuts import reverse 1、路由层 re_path(r'^test4/(d+)/',views.test4,name='list') 2、视图层 def test4(request,fp): #此处的fp用来接收正则匹配到的参数 print(reverse('list',args=(fp,))) #固定写法 return HttpResponse('ok') 3、浏览器输入 127.0.0.1:8080/test4/13145 打印的结果: /test4/13145/ 正常使用: 后端使用: print(reverse('list',args=(edit,))) 前端使用: {% url 'list' edit %} user_list = models.User.objects.all() #在数据中获取到信息列表 url(r'^edit/(d+)/',views.edit,name='edit') 前端模板语法: {%for user_obj in user_list%} <a href='edit/{{ user_obj.pk }}/'></a> {% endfor %} 视图函数: from django.shortcuts import reverse def edit(request,edit_id): url = reverse('edit',args=(edit_id,)) 模板 {% url 'edit' edit_id %}
五、有名分组反向解析 后端使用 # 后端有名分组和无名分组都可以用这种形式 print(reverse('list',args=(10,))) # 下面这个了解即可 print(reverse('list',kwargs={'year':10})) 前端使用 # 前端有名分组和无名分组都可以用这种形式 {% url 'list' 10 %} # 下面这个了解即可 {% url 'list' year=10 %} 总结:针对有名分组与无名分组的反向解析统一采用一种格式即可 后端 reverse('list',args=(10,)) # 这里的数字通常都是数据的主键值 前端 {% url 'list' 10 %} 反向解析的本质:就是获取到一个能够访问名字所对应的视图函数
六、路由分发 考虑到一个项目有多个应用 总路由不再直接做路由与视图函数的对应关系,而是将获取的路由分发给下面的app去处理对应关系. 每一个app下都可以新建自己的urls.py static文件夹 templates文件夹 from django.conf.urls import include
from app01 import app01_urls
from app02 import app02_urls 项目总路由: url(r'^app01/',include(app01_urls)), url(r'^app02/',include(app02_urls)) 应用子路由: app01.urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index) ] 接着只需要在各自的视图层写相应的逻辑代码即可! 如果两个app下的反向解析的name字段对应的名字是一样的话,反向解析不支持自动查找应用前缀! 此时引入名称空间的概念: 名称空间(了解) url(r'^app01/',include(app01_urls,namespace='app01')), url(r'^app02/',include(app02_urls,namespace='app02')) app01.urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index,name='index') ] app02.urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/',views.index,name='index') ] app01.views.py reverse('app01:index') app02.views.py reverse('app02:index') 为了避免如此麻烦,习惯上把各个app下的name字段加上前缀app01_xxx,app02_xxx即可!
七、伪静态网页 与搜索优化seo相关,实现方式: url(r'^index.html',views.index,name='app01_index') 即在路由上加上后缀.html,让动态网页看起来是静态网页。 假装自己的路径是一个静态(数据写死的)文件的路径,其实你是经过了视图函数处理,动态渲染页面。 提高百度收藏你这个网页力度,当别人搜索你这个页面相关的内容,百度会优先展示你的页面(这样虽然能提高你网页被访问概率,但是还是干不过RMB玩家)
八、django的虚拟环境的配置,自定义转换器 django2.0与django1.0的区别(了解) 1.0里面的url对应django2.0里面re_path django2.0里面的path第一个是精准匹配(你怎么写的,我就怎么匹配),不支持正则 django1.0版本中匹配到的参数都是字符串类型 django2.0转换器(了解) 1.0版本的url和2.0版本的re_path分组出来的数据都是字符串类型 默认有五个转换器,感兴趣的自己可以课下去试一下 str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式 int,匹配正整数,包含0。 slug,匹配字母、数字以及横杠、下划线组成的字符串。 uuid,匹配格式化的uuid path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?) 例如: 1、路由层 path('text/<int:id>', views.text) 2、视图层 def text(request, id): print(type(id),id) return HttpResponse('big boy') 3、浏览器输入 127.0.0.1:8000/12345 打印的结果: <class 'int'> 12345 自定义转换器 1.正则表达式 2.类 3.注册 from django.urls import path,re_path,register_converter class FoundDigitYearConverter: regex = '[0-9]{4}' def to_python(self,value): return int(value) def to_url(self,value): return '%04d'%value # 占四位,不够用0填满,超了则就按超了的位数来! register_converter(FoundDigitYearConverter, 'yyy') path('text3/<yyy:name>', views.text3)
九、FBV 与 CBV FBV:基于函数的视图 CBV:基于类的视图 CBV: from django.views import View class Login(View): def get(self,request): # return HttpResponse('get') return render(request,'login.html') def post(self,request): return HttpResponse('post') url(r'^login/',views.Login.as_view()) # >>>等价于 url(r'^login/',views.view) 详细参考博客 django 的CBV
十、视图层 前后端分离,数据的传输,通过json来做 1、拿到编码后的json字符串 import json def text5(request): res = {'name':'常山赵子龙','age':18} return HttpResponse(json.dumps(res)) # {"name": "u5e38u5c71u8d75u5b50u9f99", "age": 18} 2、汉字未被编码 import json def text5(request): res = {'name':'常山赵子龙','age':18} return HttpResponse(json.dumps(res,ensure_ascii=False)) # {"name": "常山赵子龙", "age": 18} 3、JsonResponse from django.http import JsonResponse def text5(request): res = {'name':'常山赵子龙','age':18} return JsonResponse(res) # {"name": "u5e38u5c71u8d75u5b50u9f99", "age": 18} 4、添加字典 from django.http import JsonResponse def text5(request): res = {'name':'常山赵子龙','age':18} return JsonResponse(res,json_dumps_params={'ensure_ascii':False}) # {"name": "常山赵子龙", "age": 18}
十一、上传文件 1、路由层 url(r'^upload/', views.upload) 2、视图层 def upload(request): if request.method == 'POST': print(request.FILES) file_obj = request.FILES.get('my_file') print(file_obj.name) with open(file_obj.name,'wb')as f: for line in file_obj.chunks(): #此处的chunks() 可有可无 f.write(line) return render(request,'upload.html') 3、upload.html 页面 <body> <h1>上传文件</h1> <form action="" method="post" enctype="multipart/form-data"> <input type="file" name="my_file"> <input type="submit" class="btn btn-success"> </form> </body> 注意: 上传文件时,请求方式为post, enctype=multipart/form-data, 文件的属性name需要指定。