1.rest framework serializer(序列化)的简单使用 QuerySet([obj,obj,obj]) --> JSON格式数据 0.安装和导入: pip3 install djangorestframework from rest_framework import serializers 1.简单使用 1.创建一个类,类一定要继承serializers.Serializer 2.chocie字段和FK字段都可以通过使用source来获取对应的值 3.多对多字段可以使用serializers.SerializerMethodField def get_tag(self,obj): tag_list = [] for i in obj.tag.all(): tag_list.append(i.name) return tag_list 2.使用ModelSerializer 通过配置class Meta: model = 表名 fields = ['字段',...] depth = 1
什么是RESTful
REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”。
RESTful API设计
API与用户的通信协议
总是使用HTTPs协议。
现在互联网企业,都开始关注安全了。所以,一般暴露的接口,都是使用https协议。前提是,需要购买SSL域名证书,一年花费,少则几千,多则上万。
域名
https://api.example.com 尽量将API部署在专用域名 https://example.org/api/ API很简单
使用第一种,可能会有跨域问题。为了避免这种问题,可以采用第二种。
版本
1. 将版本信息放在URL中,如:https://api.example.com/v1/ 2. 将版本信息放在请求头中。
国内的公司,一般使用第一种。前端代码不用大改动,后端开发好v2版本后。将url切换一下,就可以实现平滑迁移。
国外公司,使用会第二种,因为这样比较安全!
路径
视网络上任何东西都是资源,均使用名词表示(可复数) https://api.example.com/v1/zoos https://api.example.com/v1/animals https://api.example.com/v1/employees
上面的3个url分别表示:动物园、动物、员工
GET :从服务器取出资源(一项或多项) POST :在服务器新建一个资源 PUT :在服务器更新资源(客户端提供改变后的完整资源) PATCH :在服务器更新资源(客户端提供改变的属性) DELETE :从服务器删除资源
PATCH很少用到
过滤
通过在url上传参的形式传递搜索条件 https://api.example.com/v1/zoos?limit=10:指定返回记录的数量 https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置 https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数 https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序 https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
上面的url参数,一眼望过去,就大概知道啥意思了。所以命令规范,很重要!
程序员写代码,不只是完成功能而已!写代码的时候,必须按照规范来。比如python,遵循PEP8。
已经写好的代码,有空的时候,将代码优化一下!这样,当你把项目交接给别人的时候,不至于,让人看着代码,晦涩难懂!一万匹马在内心崩腾,有木有?
状态码
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务) 204 NO CONTENT - [DELETE]:用户删除数据成功。 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
几个常用的http状态码,需要知道。因为面试必问!
错误处理
状态码是4xx时,应返回错误信息,error当做key。
{
error: "Invalid API key"
}
尽量将代码写的健全一点,遇到错误时,抛出error
返回结果
针对不同操作,服务器向用户返回的结果应该符合以下规范
GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 PATCH /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档
比如url: http://127.0.0.1/api/comment/2 表示id为2的详细信息
Hypermedia API
RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。
{"link": {
"rel": "collection https://www.example.com/zoos",
"href": "https://api.example.com/zoos",
"title": "List of zoos",
"type": "application/vnd.yourformat+json"
}}
这个,要看需求了,有需求,可以做一下!
更多内容,请参考:阮一峰的Blog
二、基于Django实现RESTful API
在昨天项目about_drf的基础上, 增加一个评论表
修改model.py,增加表comment
# 评论表
class Comment(models.Model):
content = models.CharField(max_length=128)
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
使用2个命令,生成表
python manage.py makemigrations python manage.py migrate
现在需要对评论表,做增删改查,按照常规来讲,会这么写url
url(r'comment_list/',...), url(r'add_comment/',...), url(r'delete_comment/',...), url(r'edit_comment/',...),
现在还只是一个表的增删改查,如果有80个表呢?写320个url ?
RESTful API之url设计
路由分发
在app01(应用名)目录下,创建文件app01_urls.py
1 from django.conf.urls import url 2 from app01 import views 3 4 urlpatterns = [ 5 url(r'^article_list/', views.article_list), 6 url(r'article_detail/(\d+)', views.article_detail), 7 8 # 评论 9 url(r'comment/', views.Comment.as_view()), 10 ]
include表示导入py文件
RESTful API之视图
CBV
针对4种请求方式,使用FBV
def comment(request):
if request.method == "GET":
return HttpResponse("获取评论")
elif request.method == "POST":
return HttpResponse("创建新评论")
elif request.method == "PUT":
return HttpResponse("修改评论")
elif request.method == "DELETE":
return HttpResponse("删除评论")
这样写的话,一个4层if判断,就会有很冗长的代码。不利与维护,推荐使用CBV方式
CBV方式
from django import views
class Comment(views.View):
def get(self, request):
return HttpResponse("获取评论")
def post(self, request):
return HttpResponse("创建新评论")
def put(self, request):
return HttpResponse("修改评论")
def delete(self, request):
return HttpResponse("删除评论")
代码看着,就很清晰了。知道哪一种请求方式,该做哪些操作
APIView
之前学习django用的都是View,APIView它是什么呢?
APIView与View的区别
APIView是View的子类 传递给请求处理程序的request实例是REST框架的请求实例,而不是Django的HttpRequest实例 处理程序返回的基于REST框架的Response,而不是Django的HttpResponse,视图函数将会管理内容协商,然后设置正确的渲染方式 任何APIException将会被捕捉,然后转换成合适的response对象 接收到的请求首先被认证,然后赋予相应的权限,然后通过节流器分发给相应的请求处理函数,类似.get()和.post()
APIView是专门写API的视图函数,结合serializers,非常方便做序列化!
关于APIView的源码解析,请参考文章:
https://blog.csdn.net/u013210620/article/details/79857654
APIView的请求书,都在data里面,
但是对于GET,参数在self.request.query_params里面
修改views.py,完整代码如下:
1 from django.shortcuts import render,HttpResponse 2 from django.http import JsonResponse 3 from app01 import models 4 import json 5 from rest_framework import serializers 6 from rest_framework.views import APIView 7 8 9 # Create your views here. 10 #第二种方式 11 # def article_list(request): 12 # #去数据库查询所有的文章数据,返回queryset,每一个元素都是字典 13 # query_set = models.Article.objects.all().values("id","title","create_time","type","school") 14 # print(query_set) 15 # for i in query_set: 16 # print(i) 17 # 18 # #学校对象 19 # school_obj = models.School.objects.filter(id=i['school']).first() 20 # #学校id 21 # id = school_obj.id 22 # #学校的名字 23 # name = school_obj.name 24 # #修改字典,key为school的值 25 # i['school'] = {"id":id,"name":name} 26 # 27 # #返回json对象,safe=False表示任何能转换为json格式的对象 28 # return JsonResponse(list(query_set),safe=False) 29 # 30 31 32 class DBG(serializers.Serializer): # 声明序列化器 33 id = serializers.IntegerField() 34 title = serializers.CharField() 35 create_time = serializers.DateField() 36 type = serializers.IntegerField() 37 school = serializers.CharField(source="school.name") 38 39 40 class CYM(serializers.ModelSerializer): # 声明ModelSerializer 41 # 42 type = serializers.CharField(source='get_type_display') 43 44 class Meta: 45 model = models.Article 46 fields = "__all__" # ("id", "title", "type") 47 depth = 1 # 官方推荐不超过10层 48 49 def article_list(request): # 查询所有 50 # 去数据库查询所有的文章数据 51 query_set = models.Article.objects.all() 52 xbg = CYM(query_set, many=True) 53 print(xbg.data) 54 # 返回 55 return JsonResponse(xbg.data, safe=False) 56 57 def article_detail(request,id): #查询单条数据 58 article_obj = models.objects.filter(id=id).first() 59 xcym = CYM(article_obj) 60 return JsonResponse(xcym.data) 61 62 class Comment(APIView): 63 def get(self,request): 64 print(request) 65 print(self.request.query_params) #get请求参数 66 print(self.request.data) #其他请求方式参数,比如POST,PUT 67 return HttpResponse("获取评论") 68 69 def post(self,request): 70 print(self.request.query_params) #get请求参数 71 print(self.request.data) #其他请求方式参数,比如:post,put 72 return HttpResponse("创建新评论") 73 74 def put(self,request): 75 return HttpResponse("修改评论") 76 77 def delate(self,request): 78 return HttpResponse("删除评论") 79