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     
Views.py

相关文章:

  • 2022-12-23
  • 2021-05-28
  • 2021-01-18
  • 2021-10-30
  • 2018-09-20
  • 2021-08-15
猜你喜欢
  • 2022-12-23
  • 2021-06-09
  • 2022-12-23
  • 2022-01-24
  • 2021-06-01
  • 2021-08-08
相关资源
相似解决方案