restful——规范 + APIview
一、 什么是RESTful
- REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
- REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
- 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
- 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)
10个规范:
-与后台做交互,通常使用https
-域名: -https://api.baidu.com(存在跨域问题) -https://www.baidu.com/api/
-版本 -https://www.baidu.com/api/v1 -https://www.baidu.com/api/v2
-路径,视网络上任何东西都是资源,均使用名词表示(可复数) -https://api.example.com/v1/books 不是:https://api.example.com/v1/delete_one_book
-method来表示增删查改 -https://api.example.com/v1/books get请求,获取所有书 -https://api.example.com/v1/books post请求,新增一本书 -https://api.example.com/v1/book/1 delete请求,删除一本书 -https://api.example.com/v1/book/1 delete请求,获取id为1的这本书 -https://api.example.com/v1/book/1 put/patch请求,修改id为1的这本书 -过滤,通过在url上传参的形式传递搜索条件 -https://api.example.com/v1/books?limit=10:只拿前10本 -https://api.example.com/v1/books?price=10:只拿价格为10的书
-状态码 -{status:100,}
-错误处理,应返回错误信息,error当做key { status:101, errors:'您没有权限操作这个事' }
-返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范 GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 PATCH /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档
-返回结果中提供链接(获取一本书) { id:1 name:lxx price:12 publish:www.xx.com/api/v1/publish/1 }
二、 基于Django实现
-在URL中:
url(r'^books/', views.Books.as_view()), url(r'^book/(?P<id>\d+)', views.Book.as_view()),
-在views:
import json def user2(request): if request.method=='GET': dic = {'status':200,'name': 'lqz2', 'age': 18} return HttpResponse(json.dumps(dic)) elif request.method=='POST': dic = {'status': 200, 'msg': '修改成功'} return JsonResponse(dic) class Users(View): def get(self, request): dic = {'status':200,'name': 'lqz', 'age': 18} return HttpResponse(json.dumps(dic)) def post(self, request): dic = {'status': 200, 'msg': '修改成功'} return JsonResponse(dic)
三、APIVIew源码分析
Django执行流程:请求来 中间件 > URL 中匹配成功执行 as_view > dispatch 方法,重新封装了request > initialize_request > initial > 认证组件 > 权限
组件 > 频率件 > views中 > 中间件 > 响应。
第一步:
第二步:
第三步:
第三步:
第四步:
ps:dispatch方法
# 传入的request是原生的request对象 # 接收的request已经不是原生的request了,但是它内部有个原生的request对象 request = self.initialize_request(request, *args, **kwargs) self.initial(request, *args, **kwargs)#这里面有权限,认证,频率
四、restframework---Serializer
干什么用的? 把python中的对象,转成json格式字符串--------序列化
models:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db import models # Create your models here. class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author") def __str__(self): return self.title class Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() def __str__(self): return self.name class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() def __str__(self): return self.name
# 写一个类继承 serializers.Serializer class BookSerializer(serializers.Serializer): id = serializers.CharField() # 通过source可以改名 name = serializers.CharField(source='title') # 名称必须和表字段名相同 price = serializers.CharField() xxx = serializers.CharField(source='test') # 1 变量名和source指定的值不能一样 # 2 source='publish.name'还支持继续 . # 3 source 还支持方法(没用) # publish_name = serializers.CharField(source='publish.name') # publish_id = serializers.CharField(source='publish.pk') # 4 支持写方法,如下 #方法一定传一个参数,是当前book对象 publish_dic=serializers.SerializerMethodField() def get_publish_dic(self,obj): # 猜,这个obj应该是谁,当前book对象 return {'id':obj.publish.pk,'name':obj.publish.name} authors=serializers.SerializerMethodField() # def get_authors(self,obj): # # 所有作者queryset对象 # author_list=obj.authors.all() # ll=[ {'name':author.name,'id':author.pk} for author in author_list] # return ll def get_authors(self,obj): # 所有作者queryset对象 author_list=obj.authors.all() author_ser=AuthorSer(instance=author_list,many=True) return author_ser.data
views:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db import models # Create your models here. class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author") def __str__(self): return self.title class Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() def __str__(self): return self.name class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() def __str__(self): return self.name
注意:
source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号(authors=serializers.CharField(source='authors.all'))
如在模型中定义一个方法,直接可以在在source指定执行
choices:
class UserInfo(models.Model): # 通过 XXX_choices =( ("1","普通用户"), ) 1 为 真实数据,"普通用户"是为显示直观的名字 user_type_choices = ( (1,'普通用户'), (2,'VIP'), (3,'SVIP'), ) #通过choices 绑定关系 user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=64) #视图 ret=models.UserInfo.objects.filter(pk=1).first() aa=ret.get_user_type_display() #通过get_Foo_display方法获取user_type_choices中元组的第二元素值 xx=serializers.CharField(source='get_user_type_display') #其中Foo为字段名
五、ModelSerializer
跟表模型绑定的序列化
from app01 import models # ModelSerializer跟表模型绑定的序列化 class BookSerializer(serializers.ModelSerializer): class Meta: # 指定表模型 model = models.Book # 序列化所有字段 fields = '__all__' # 只想序列化title和id这俩字段 # fields = ['title', 'id'] # exclude 和fields 不要连用 # exclude = ['title'] # 深度,表示连表的深度 # 不建议使用:下几层要取得参数不能控制,官方建议不要超过10,我给你的建议不要超过3 # depth=1 # 全取出来之后,可以在后面覆盖之前的值 # 如果想让publish字段显示出版社的名字 # publish = serializers.CharField(source='publish.name') # authors = serializers.SerializerMethodField() # def get_authors(self, obj): # author_list = obj.authors.all() # author_ser = AuthorSer(instance=author_list, many=True) # return author_ser.data title = serializers.CharField(max_length=6, min_length=3, error_messages={'max_length': '太长了'}) # 也有局部钩子和全局钩子 def validate_title(self, value): from rest_framework import exceptions print(value) if value.startswith('sb'): raise exceptions.ValidationError('不能以sb开头') return value
六、Django restframewor之序列化
-干什么用的? 把python中的对象,转成json格式字符串
-1 写一个类继承 class BookSerializer(serializers.Serializer): id = serializers.CharField() title = serializers.CharField() price = serializers.CharField() -2 使用(视图类中) # 写一个获取所有图书的接口 class Books(APIView): def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '成功'} book_list = models.Book.objects.all() # 第一个参数是要序列化的queryset对象,如果序列化多条,必须指定many=True # 问?什么情况下many=False,instance=单个对象的时候 book_ser = BookSerializer(book_list, many=True) print(book_ser.data) #序列化完成得到的字典 response['books'] = book_ser.data return Response(response)
实例:
序列化类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from app01 import models from rest_framework import serializers class BookSerializer(serializers.ModelSerializer): class Meta: # 指定表模型 model = models.Book # 序列化所有字段 fields = '__all__'
表模型:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Book(models.Model): title = models.CharField(max_length=32) price = models.IntegerField() pub_date = models.DateField() publish = models.ForeignKey("Publish") authors = models.ManyToManyField("Author") def test(self): return self.title + str(self.price) def __str__(self): return self.title class Publish(models.Model): name = models.CharField(max_length=32) email = models.EmailField() # def __str__(self): # return self.name # return str(self.pk) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField()
views代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 写一个获取所有图书的接口 class Books(APIView): authentication_classes=[Auth,] def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '成功'} book_list = models.Book.objects.all() # 第一个参数是要序列化的queryset对象,如果序列化多条,必须指定many=True # 问?什么情况下many=False,instance=单个对象的时候 book_ser = BookSerializer(book_list, many=True) print(book_ser.data) response['books'] = book_ser.data return Response(response) #增 def post(self, request): response = {'status': 100, 'msg': '成功'} # 提交的字典 # book = request.data # 传统方法,创建对象保存 # 新方法,通过序列化组件保存,必须用继承自ModelSerializer # data注意是data print(request.data) book_ser = BookSerializer(data=request.data) # is_valid提交的字段校验通过 if book_ser.is_valid(): book_ser.save() response['book'] = book_ser.data else: response['msg'] = book_ser.errors # return Response(book_ser.data) return Response(response) #改 def put(self, request): # print(request.data) id = request.data.get("id") # print(id) response = {'status': 100, 'msg': '成功'} book = models.Book.objects.filter(pk=id).first() # 修改的话,要把book对象传过来 book_ser = BookSerializer(data=request.data, instance=book) # is_valid提交的字段校验通过 if book_ser.is_valid(): # save既可以修改,又可以更新 book_ser.save() response['book'] = book_ser.data else: response['msg'] = book_ser.errors # return Response(book_ser.data) return Response(response) #删 def delete(self,request): id = request.data.get("id") response = {'status': 100, 'msg': '删除成功'} book = models.Book.objects.filter(pk=id).delete() return Response(response)
在线格式化json:
-https://www.json.cn/