Django复习
1、HTTP协议
HTTP协议 -请求协议(wsgi协议负责拆) -请求首行:get/http/1.1 -请求头部:key:value的形式,有编码方式contenttype,referer,useragent -请求体:urlencode编码方式,是可以直接被django解析的,name=lww&name=18,django会拆到大写的POST中 formdata编码方式:上传文件的,--sfsjf--格式,数据django会拆到POST中,文件会拆到request.FILES中 json:原生的django处理不了,body体中取出自行处理,drf中可以request.data中可以取出
PS:前台传过来json格式,每次都要自己取,这样很麻烦,我封装了一个方法paserRequest,将body体中的数据出来放到request.data中再返回request,之后每次需要解析json格式调一下就可以了,后来又给修改成了装饰器,装饰器里面还可以加认证,频率等功能
-响应协议
-响应首行:HTTP/1.1 200 ok/r/n
-响应头部:key:value的形式
-响应体:响应体的内容才是我们看到的html页面的东西,页面渲染出来的东西
-特性:
-在tcp/ip协议之上
-无状态,所以才引出了cookie,cookie不安全,发展到session,session对服务器有压力,又有了token
-无连接,连一次后直接断开,socket是一直连着
-请求、响应,发一个请求给一个响应,响应后就断开
服务器主动推送消息:
1、轮询:用ajax间隔几秒就向服务器发送请求
2、长轮询:发过请求后在那挂10秒,10秒后断开再发一次请求,10秒内有消息的话就接收并显示出来(主流网站都是用长轮询)
3、websocket:有的浏览器不兼容
djang请求生命周期 1:浏览器发起请求 2:WSGI创建socket服务端,接收请求(Httprequest) 3:中间件处理请求 4:url路由,根据当前请求的URL找到视图函数 5:view视图,进行业务处理(ORM处理数据,从数据库取到数据返回给view视图;view视图将数据渲染到template模板;将数据返回) 6:中间件处理响应 7:WSGI返回响应(HttpResponse) 8:浏览器渲染
2、django路由层
1 基本路由 url('正则表达式', 函数地址, {默认值}, name=‘test') 2 有名分组/无名分组:url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), 3 路由的分发:include,url('app01/', include(urls)),app01/后不要加终止符$
4 反向解析:解决路由可能改变的情况,通过url里name动态解析出路由地址,视图层url=reverse('test'),模板层{% url 'test' %}
5、名称空间:url(r'app01/',include('app01.urls',namespace='app01'),name='index'),视图层url=reverse('app01:index'),模板层{% url 'app01:test' %}
遇到的问题:一开始不知道有名称空间,项目中用方向解析的时候,总是重定向不对,因为是多人协同开发的,后来发现是和同事命名一样了,后来上网查找有名称空间这个东西
6、django2.0的re_path和1.0的url一样,一开始用的1.几的版本,后来用的2.几
3、视图层
-fbv request-post提交数据,在浏览器窗口里也可以携带数据,从GET中取 response:render,HttpResponse,redirect,JsonResponse:JsonResponse(dic,json_dumps_params={'ensure_ascii':True})解决乱码问题 -cbv
4、模型层
db_constraint 取消外键关联 查询不受影响 级联删除,on_delete=models.SET_CASCASE,models.SET_NULL,级联删除可以设置默认值,也可以设置为空 多表查询: --title__contains="python"--转成的sql like %python% --基于对象的跨表查询 -一对一: 正向查:按字段 反向:按表名小写 -一对多 正向查:按字段 反向:按表名小写_set -多对多 正向查:按字段 反向:按表名小写_set 表名小写_set 可以重命名:related_name='xxx' --基于双下划线查询 正向 ----》关联字段在那个表,从哪个表往外查 反向 ----》关联字段不在我这个表,从我这个表往外查 手机号以151开头的作者出版过的所有书籍名称以及出版社名称 Authordetail.objects.filter(phone__startswith='151').values('author__book__name','author__book__publish__name') Authordetail.objects.filter(phone__startswith='151').values('author__yyy__name','author__book__publish__name') 反向查询—— related_query_name='yyy' 聚合:aggregate,Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
分组:annotate values在前表示:group by values在后:要取出来的东西 filter在前:where条件 filter在后:having 统计每一本以py开头的书籍的作者个数 Book.objects.all().filter(name__startswith='py').annotate(num_authors=Count('authors')).values('num_authors')
-F查询:比较和运算
-Q查询:与或非
5 组件
分页器:paginator forms组件:form表单提交的数据,ajax提交的json数据都可以校验,只要是字典就可以 -渲染页面 -渲染数据信息 -数据校验 cookie与session组件: -session默认存数据库中,可以配置存到Redis中,可以缓存session(默认内存缓存,可以通过配置存到Redis或memcache)
中间件组件:对请求和相应进行拦截
-请求process_request
-响应process_response
Auth模块
-使用:用anth模块,创建表的时候要继承auth的那个表AbstractUser,可以写一些新的字段,settings中需要配置AUTH_USER_MODEL ='app01.UserInfo'
-认证
-用户登录状态
6 DRF
restful规范: 1、建议使用HTTPS(有证书,数据传输的时候加密了,更安全一些) 2、域名使用api的方式 3、版本拼在后面或放请求体中 4、路径以名词表示 5、method,GET--获取数据,POST--创建资源,PUT--修改资源,PATCH--修改资源,DELETE-删除资源(其中PUT和PATCH是幂等的) 6、过滤,可以在url上传参的形式传递搜索条件 7、状态码,在技术文档上 8、错误处理,应返回错误信息,error当做key。 9、返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范。 GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 PATCH /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档 10、返回结果中提供链接
基于DRF的增删改查接口写法示例
路由
url(r'Publish/', views.Publish.as_view({'get': 'get_all', 'post': 'new_publish'})) url(r'Publish/(\d+)', views.Publish.as_view({'get': 'get_one'}))
视图
from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.viewsets import ViewSetMixin from app01 import models from rest_framework import serializers class PublishSer(serializers.ModelSerializer):
#序列化 class Meta: model = models.Publish fields = '__all__' class MyResponse(): def __init__(self): self.status = 100 self.msg = None @property def get_dic(self): return self.__dict__ class Publish(ViewSetMixin, APIView): def get_all(self, request): response = MyResponse() publish_list = models.Publish.objects.all() ser = PublishSer(publish_list, many=True) response.msg = '查询成功' response.data = ser.data return Response(response.get_dic) def new_publish(self, request): response = MyResponse() ser = PublishSer(data=request.data) ser.save() response.msg = '添加成功' response.data = ser.data return Response(response.get_dic)