欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DRF

程序员文章站 2022-07-12 11:12:30
...

DRF

Restful 理解

只是一个设计规范, 每个URL 是一种资源,并且 设置了请求头 和返回 资源格式,  设置了基本的操作 方法  增删改查 , get post put delete  patch 
URL:
尽量用名词复数形式,与数据库的表名对应
过滤条件:
?page=2&size=10
域名:
尽量使用专用域名
版本:
在url 中呈现版本
状态码
200  获取成功
201 创建成功
204 删除成功
400 用户请求有误(请求参数有误)
401 用户没有权限,(没有登录) 
403 没有授权(可以登录,但是没有授权)
404 用户请求的路径不存在
500 服务器错误
错误处理 
{ “details”: “身份证信息错误”,

“status_code”:401  
}
超链接API 
响应数据要 提示下页的链接

View   是Django 自带的

get:
需要queryset for循环加append dict转化为dict,然后返回前端
Post:201
1.首先获取 request (requst.body 就是一个json),校验数据类型对不对, 是否必填都有了, 唯一校验是否能通过,然后再反序列化   , 然后再创建 ,如果返回创建的数据也要继续走get 的流程 
json_data=reqeust.body
python_data=json.loads(json_data)
Project.objects.create(**python_data[“name”])   
Update:
1.校验 前端Pk
2.获取 Pk 项目,
3.获取json 数据   ,并校验数据,然后转化为dict , 把值 赋给 Pk 对象  ,并更新
4.已经保存的project 实例,组成dict返回前端  Delete
1.校验 PK
2.获取pk,并 delete
3. 状态码是 204

流程为:

1.校验用户输入
2.将请求的数据 转化为 模型类的对象
反序列化  将其他格式转为程序的数据类型
3.操作数据库
4. 将模型类对象转化为 其他数据  如json格式
序列化 程序中的数据转为 其提供格式 Json XML

增加:

校验请求参数>反序列化>保存数据>保存的数据进行序列化返回
删除
判断是否存在》删除数据库
改:
校验请求参数》反序列化》操作数据库保存>返回操作数据
查:
校验 Pk>序列化进行返回

Django之model_to_dict将一个对象变成字典

goods = Goods.objects.all()[:10]
json_list = []
for good in goods:
  json_dict = model_to_dict(good)
  json_list.append(json_dict)

HTTPResponse 后端要用 json 模块序列化,前端也要反序列化。

JSonResponse 前端不用反序列化,只能传输字典,不能传输字符串。

缺点 :

代码冗余有严重,
数据校验非常麻烦,可复用差
编码没有统一规范
仅支持json格式传参,不支持form表单
仅能返回json 格式的数据,其他类型不支持
视图没有过滤,排序 ,功能非常差

Django Rest Framework

在django 基础上进行二次开发, 构建了 Restful API

特性:

  1. 强大的 serializer 序列化器, 可以高效的进行序列化与反序列化操作
  2. 提供丰富的类视图, Mixin 扩展类, Viewset 视图类
    3.提供直观的web API 界面
  3. 多种身份认证,和权限认证
    5.强大的 排序 ,过滤, 分页 ,搜索 
    可扩展 ,插件丰富

DRF 序列化器

序列化器 里定义的字段就是显示的字段,  如果不想写 可以直接 写  fields=“all

1.序列化
queryset=Projects.objects.all()
serializer=ProjectSerializers(instance=queryset)
如果是多个数据模型 就需要 加上
serializer=ProjectSerializers(instance=queryset,many=True)
获取值 用seriliazer.data   ,就可以返回了 .
2.反序列化 
1.校验
2.创建  
3.保存
json_data=request.body
serializer=ProjectSerializer(data=json_data)
校验
serializer.is_valid()   返回True 就是校验通过
当填入 raise_exception=True  ,那么校验失败之后会抛出异常 , 
try :
serializer.is_valid(raise_exception=True)
except as e :
  return  JsonResponse(serializer.errors)
成功后的数据 可以用  serializer.valiated_data 
如果想指定字段输出  read_only=True
id=serializers.IntergeField(Label=“ID”, read_only=True)
如果想指定字段反序列化输入,不对序列化输出:
id=serializers.IntergeField(Label=“ID”, write_only=True)
想校验 Pk 的方法为 :
1. 使用函数抓取
try :
Project.objects.get(id=pk)
except Project.DoesNotEixit:
  raise Http404

想校验 Pk 的方法为 :

1. 使用函数抓取
def get_object():
try :
Project.objects.get(id=pk)
except Project.DoesNotEixit:
  raise Http404

好处 : 模型类 转为json  , json 转为 模型类, 校验

序列化校验

1.定义字段的类型 是第一层校验

  1. 在定义序列化字段中定义  validators  》UniqueValidator  就是一个 唯一校验
    name=serializers.CharField(label=“项目名称”,max_length=200,help_text=“项目名称”,validators=[UniqueValidator(querySet=Porjects.objects.all(),message=“不能重复”)])
  2. 自定义校验器:类外边
    定义的函数 参数 : 字段名称 ,name  传入自定义校验器, 如果校验失败, 抛出异常 raise serializes.ValidationError(“项目名称不正确”), 放到validators 列表里 
    4. 类内部 编写 validate_ 跟上校验的字段 , 参数是前端传递的 字段的value .  切记要return value 
    def validate_name(self,value):
    5. 多字段的校验
    用  def validate(self ,attrs)attrs 是传过来的dict ,这个时候就可以 判断数据, 然后return 
    这个很重要,

序列化 数据库操作

在序列化器中定义 def cerate(self, validated_data)

return   project.objects.create(**validated_data)
def update(self,instance, validated_data)
instance.name=validated_data[“name”]
切记 要return  更新的模型对象

继承 modelserializer

定义 class Meta :

model=Projects
fields=(“id”,“name”)
exclude=(“publicAPP”) 排除
read_only_fields=(“name”)

write_only_fields=(“name”)

手动添加校验器,需要重写覆盖,所有校验方法一样, 包括自定义的函数, validate 和 validate_name

name= serializers.CharField(lable, validators=[],error_messages={‘max_length’:“长度不能超过200个字节”})

参数修改

extra_kwargs = {
“leader”:{
   “write_only”:True,
“error_messages”:{‘max_length’:“长度不能超过200个字节”}
}
}

自动创建 def create 和 def update()

APIView

APIView 与 View 的不同之处在于:

传入到视图方法中的是REST framework的 Request 对象(支持form表单和 json 进行了扩展),而不是Django的 HttpRequeset 对象;
视图方法可以返回REST framework的 Response 对象,(可以返回json 也可以返回html 默认是json)视图会为响应数据设置 render 符合前端要求的格式;
任何 APIException 异常都会被捕获到,并且处理成合适的响应信息;
在进行 dispatch() 分发前,会对请求进行身份认证、权限检查、流量控制

支持定义的属性:
authentication_classes  列表或元祖,身份认证类
permissoin_classes  列表或元祖,权限检查类
throttle_classes  列表或元祖,流量控制类
缺点:
排序,过滤 和 分页 没有这个功能

GenericApiView

注意必须指定queryset 和 serializeer_class

queryset=Projects.objects.all()
serializer_class=ProjectModelSerializer

必须执行哦

自动提供 get_object() 方法, 这样就不需要 自己写了 ,

self.get_object()  会返回详情视图所有模型类对象。
不需要这样获取序列化器, 
serialize=Projectserializer(instance=project)
上边不要这么用例 ,
直接 serializer= self.get_serializer(instance=project)
serializer= self.get_serializer(instance=project,data=data)

总结:

1.指定 查询集
2.指定序列化器
3. 可以通过get_object 获取模型对象
4.可以通过 get_serializer(instance=project) 获取序列化器
5. 指定排序引擎并设置字段
filter_backends=[filters.OrderingFilter]
ordering_fields=[“id”,“name”]
6. 获取查询集
project_qs=self.get_queryset()
7. 排序查询集
serializer = self.filter_queryset(project_qs)
8. 设置全局排序
在类视图中设置filter_backends,使用 rest_framework.filters.OrderingFilter
只能继承GernericApiView
9. 过滤
pip install django-filter
REST_FRAMEWORK = {
‘DEFAULT_FILTER_BACKENDS’: (‘django_filters.rest_framework.DjangoFilterBackend’,) # 全局配置,对全部视图的查询多条接口都有过滤功能,但是视图里要指定字段
filter_fields = (‘gender’, ‘department’)

127.0.0.1/employees?gender=1
10. 分页
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
‘PAGE_SIZE’: 10, # 这是每页显示的数目 ,必须指定分页的条数
可以用调用方法
page=self,.paginate_queryset(project_qs)
如果没有指定引擎就返回None
serializer=self.get_serializer(instance=page,many=True)
return self.get_paginated_response(serializer.data) 
这里面会自动添加 counter,next ,previous, results
可以自定义 分页
class GoodsPagination(PageNumberPagination):
‘’’
商品列表自定义分页
‘’’ #默认每页显示的个数
page_size = 10
#可以动态改变每页显示的个数
page_size_query_param = ‘page_size’ #页码参数
page_query_param = ‘page’ #最多能显示多少页
max_page_size = 100
在视图使用  
pagination_class = GoodsPagination #分页

post

Put

待解决的问题以及痛点

需要 创建两个类, 一个是 PK 类 ,一个是聚集类
URL 需要创建两个 ,对一个details 和 不是 
实际要写两份, 不能合并为一个, 一个类不能创建两个get 方法  一个是详情,一个是聚集

解决方法 引入扩展类  Mixins.py

Mixin

CreateModelMixin

ListModelMixin
RetrieveModelMixin
UpdateModelMixin
DestroyModelMixin

结合GenericApiView

CreateAPIView(mixins.CreateModelMixin,
                GenericAPIView):   创建create 
ListAPIView(mixins.ListModelMixin,
              GenericAPIView):   get_querySet
RetrieveAPIView(mixins.RetrieveModelMixin,
                  GenericAPIView):

获取details

DestroyAPIView(mixins.DestroyModelMixin,
                 GenericAPIView):

delete details

UpdateAPIView(mixins.UpdateModelMixin,
                GenericAPIView):
ListCreateAPIView(mixins.ListModelMixin,
                    mixins.CreateModelMixin,
                    GenericAPIView):
RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
                        mixins.UpdateModelMixin,
                        GenericAPIView):
RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
                         mixins.DestroyModelMixin,
                         GenericAPIView):
RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                               mixins.UpdateModelMixin,
                               mixins.DestroyModelMixin,
                               GenericAPIView):