ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Django REST framework入门规范,序列化器-Serializer

2021-04-13 16:02:13  阅读:126  来源: 互联网

标签:请求 self request REST Django 接口 序列化 name


前后端开发模式

在开发Web应用中,有两种应用模式:

前后端不分离

002

前后端分离

001

api接口

为了在团队内部形成共识、防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写的接口,用途一目了然,减少双方之间的合作成本。

规定了前后台信息交互规则的url链接,也就是前后台信息交互的媒介

接口文档

一旦前后端分离以后,前端根本不清楚后端在写什么,要求的参数是什么不知道,返回什么格式的数据也不知道,所以每写一个接口,就要写一个接口文档

  • 可以手动写(公司有平台,录到平台里)

  • 自动生成(coreapi,swagger)

restful规范

REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征性状态转移)。

RESTful是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中。

这种风格的理念认为后端开发任务就是提供数据的,对外提供的是数据资源的访问接口,所以在定义接口时,客户端访问的URL路径就表示这种要操作的数据资源。

在前后端不分离的项目中,网页所需要的数据可以直接通过模板渲染的方式传递到前端页面,并且可以很好的支持django自带的各种验证工具,比如csrfmiddleware

但在前后端分离的项目中,前后端的数据通信普遍通过json字符串的形式通信,那么我们就需要有个标准去定义前后端沟通方式或者说格式

restful就是来干这件事情的,它是一种面向资源的架构,规定API如何编写,通过它我们可以让api更加简洁可维护,是对于我们写程序的一些规范

事实上,我们可以使用任何一个框架都可以实现符合restful规范的API接口。

restful规范只是一种规范(10条,规定了这么做,并不是强制性的,公司可以不采用,可以结合自身需要去做适配和调整)

1 数据的安全保障,通常使用https进行传输

url链接一般都采用https协议进行传输

注:采用https协议,可以提高数据交互过程中的安全性

2 域名有区分(路径中带api标识)

https://api.example.com  # 尽量将API部署在专用域名
https://127.0.0.0:8080/api/    # API很简单

3 多版本共存:请求地址中带版本,或者在请求头中

https://127.0.0.0:8080/api/v1/  # 这里的v1表示接口版本

4 任何东西都是资源,均使用名词表示 (尽量不要用动词)

https://api.example.com/v1/books/  book即是名词,不再出现动词表示操作了
https://api.example.com/v1/get_all_books(不符合规范)

5 通过请求方式区分不同操作

get 请求:获取数据
post 请求:新增数据
put/patch 请求:patch是局部更新,put是全部更新(基本上更新都用put)
delete 请求:删除

6 在请求路径中带过滤

https://api.example.com/v1/?name='金'&order=asc
https://api.example.com/v1/name?sortby=name&order=asc

7 返回中带状态码

json数据带状态码:自己定义的,http响应中带状态码(标志当次请求成功或失败)

 - 正常响应
    响应状态码2xx
      200:常规请求
      201:创建成功
- 重定向响应
    响应状态码3xx
      301:永久重定向
      302:暂时重定向
- 客户端异常
    响应状态码4xx
      403:请求无权限
      404:请求路径不存在
      405:请求方法不存在
- 服务器异常
    响应状态码5xx
      500:服务器异常

8 返回数据中带错误信息

错误处理,应返回错误信息,error当做key

response['status'] = 101
response['msg'] = '验证码错误'

9 对不同操作,返回数据符合如下规范(这只是规范)

GET /books:返回资源对象的列表(数组)[{},{},{}]
GET /books/1:返回单个资源对象   {}
POST /books:返回新生成的资源对象 {新增的书}
PUT /books/1:返回完整的资源对象   {返回修改后的}
PATCH /books/1: 返回完整的资源对象 {返回修改后的}
DELETE /books/1:返回一个空文档  

{status:100,msg:查询成功,data:null}

10 返回结果中带链接

 

postman的使用

Postman是一款接口调试工具,是一款免费的可视化软件,同时支持各种操作系统平台,是测试接口的首选工具。

模拟发送http请求,携带数据(请求地址,请求头,请求体,编码格式) 快速把接口导入导出

1 后端写好接口要测试,后端开发要使用一个工具测试接口(postman)
2 下载---一路下一步--装成功了
3 会发送http请求,get,post请求即可
4 请求地址带参数,请求体带数据,请求头加数据
5 响应cookie,响应头,响应体

Django Rest_Framework介绍和安装

核心思想: 缩减编写api接口的代码

Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用。在REST framework中,提供了序列化器Serialzier的定义,可以帮助我们简化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持。REST framework提供了一个API 的Web可视化界面来方便查看测试接口。

特点

  • 提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;

  • 提供了丰富的类视图、Mixin扩展类,简化视图的编写;

  • 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;

  • 多种身份认证和权限认证方式的支持;[jwt]

  • 内置了限流系统;

  • 直观的 API web 界面;

  • 可扩展性,插件丰富

1 可以更方便的使用django写出符合resful规范的接口(不用也可以写符合规范的接口)
2 是一个app
3 安装 pip3 install djangorestframework
4 https://www.django-rest-framework.org/

drf 简单使用(csrf已经禁用掉了)

# 路由
path('test/', views.Test.as_view()),
# 视图类
from rest_framework.views import APIView
from rest_framework.response import Response
class Test(APIView):
   def get(self,request):
       return Response({'name':'lqz','age':'19'})
   def post(self,request):
       return Response({'name': 'egon', 'age': '19'})
# 注册app
INSTALLED_APPS = [

   'rest_framework'
]
# 在请求地址中访问
http://127.0.0.1:8001/test/

drf快速使用

# 在setting的app中配置

INSTALLED_APPS = [
   'rest_framework'
]


# 视图 views.py

from rest_framework.viewsets import ModelViewSet
from app import models
from app.serializer import  BookSerializer
class BookView(ModelViewSet):
   serializer_class =BookSerializer
   
   
# 路由 urls.py

from rest_framework.routers import SimpleRouter
from app import views

router = SimpleRouter()
router.register('books', views.BookView)
urlpatterns = [
   path('admin/', admin.site.urls),
]
urlpatterns += router.urls


# 序列化器 serializer.py (需要手动创建)

from rest_framework.serializers import ModelSerializer
from app import models
class BookSerializer(ModelSerializer):
   class Meta:
       model = models.Book
       fields = '__all__'


# 模型层 models.py

from django.db import models
class Book(models.Model):
   name = models.CharField(max_length=32)
   publish = models.CharField(max_length=32)
   price = models.IntegerField()


CBV源码分析和APIView源码分析

cbv执行流程

    path('test/',views.TestView.as_view()),
   # path('test/',View类的as_view内部有个view闭包函数内存地址),
   '''
  1 path的第二个参数是:View类的as_view内部有个view闭包函数内存地址
  2 一旦有请求来了,匹配test路径成功
  3 执行第二个参数view函数内存地址(requset)
  4 本质执行了self.dispatch(request)
  5 通过反射去获得方法(如果是get请求,就是get方法)
    if request.method.lower() in self.http_method_names:
      handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
  6 执行get方法,传入参数
  handler(request, *args, **kwargs)
  '''

APIView的执行流程

    # path('test/',APIView类的as_view内部是用了View的as_view内的view闭包函数),
   '''
  1 path的第二个参数是:APIView类的as_view内部使用了View的as_view内的view闭包函数
  2 一旦有请求来了,匹配test路径成功
  3 执行第二个参数view函数内存地址(requset),还是执行View的as_view内的view闭包函数,但是加了个csrf_exempt装饰器
  4 所以,继承了APIView的所有接口,都没有csrf的校验了 (*****************)
  5 执行self.dispatch(request)----》APIView类的
      def dispatch(self, request, *args, **kwargs):
          # 以后所有的request对象,都是****新的request对象***,它是drf的Request类的对象
          request = self.initialize_request(request, *args, **kwargs)
          self.request = request
          try:
              #整个drf的执行流程内的权限,频率,认证
              self.initial(request, *args, **kwargs)
              if request.method.lower() in self.http_method_names:
                  handler = getattr(self, request.method.lower(),
                                    self.http_method_not_allowed)
              else:
                  handler = self.http_method_not_allowed
   
              response = handler(request, *args, **kwargs)
   
          except Exception as exc:
              # 全局异常
              response = self.handle_exception(exc)
          # 响应
          self.response = self.finalize_response(request, response, *args, **kwargs)
          return self.response

  '''
   
### request = self.initialize_request(request, *args, **kwargs)
##返回的request对象是drf   Request类的request对象
def initialize_request(self, request, *args, **kwargs):
   return Request(
       request,
       parsers=self.get_parsers(),
       authenticators=self.get_authenticators(),
       negotiator=self.get_content_negotiator(),
       parser_context=parser_context
  )
### *******以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了



#####你需要记住的
-0 所有的csrf都不校验了
-1 request对象变成了新的request对象,drf的request对象
   -2 执行了权限,频率,认证
   -3 捕获了全局异常(统一处理异常)
   -4 处理了response对象,如果浏览器访问是一个样,postman访问又一个样
   -5 以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了
 

Request对象分析

1 django 原生的Request:
django.core.handlers.wsgi.WSGIRequest
2 drf的Request:
rest_framework.request.Request

3 drf的request对象内有原生的request
request._request:原生的Request
4 在视图类中使用
request.method  拿到的就是请求方式,
   正常拿,应该request._request.method
5 如何实现这种操作?
-对象.属性会触发 类的__getattr__方法
   
   
6 drf的Request类重写了__getattr__
   def __getattr__(self, attr):
       try:
           # 去原生的request反射属性
           return getattr(self._request, attr)
       except AttributeError:
           return self.__getattribute__(attr)
       
       
7 虽然视图类中request对象变成了drf的request,但是用起来,跟原来的一样,只不过它多了一些属性
第一个:request.data   # post请求提交的数据,不论什么格式,都在它中
   第二个:requst.query_params # get请求提交的数据(查询参数)
   
   
8 重点记住:
-drf的request对象用起来跟原来一样(重写了__getattr__)
   -request.data  # post请求提交的数据,不论什么格式,都在它中
   -requst.query_params  # get请求提交的数据(查询参数)

序列化器-Serializer

序列化器的作用

1 序列化:把python中的对象转成json格式字符串
序列化器会把模型对象转换成字典,经过response以后变成json字符串
2 反序列化:把json格式字符串转成python中的对象
把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型

3 注意:drf的序列化组件(序列化器)
把对象(Book,queryset对象)转成字典
   因为有字典,直接丢到Response中就可以了

 

序列化器的使用

Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer

1 写一个序列化的类,继承Serializer
class BookSerializer(serializers.Serializer):
   # 在这里写要序列化的字段
   # 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
   # 字段类,有很多字段参数()
   name = serializers.CharField()
   price = serializers.IntegerField()
   # publish = serializers.CharField()
2 在类中写要序列化的字段(常用字段,和非常用字段)(字段参数)
name = serializers.CharField()
   price = serializers.IntegerField()
3 在视图类中使用(实例化得到一个序列化类的对象,传入要序列化的数据)
class BookView(APIView):
   def get(self, request):
       book_list = models.Book.objects.all()
       # instance=None, 要序列化的数据
       # data=empty ,要反序列化的数据(目前data先不用)
       # many=True 如果序列化多条,一定要写many=True
       book_ser = BookSerializer(instance=book_list, many=True)
       # book_ser.data就是序列化后的数据
       return Response(book_ser.data)
4 得到序列化后的数据,返回(对象.data---》就是字典)
book_ser.data
   
5 字段参数,source,指定要序列化表中的哪个字段

image-20210413151552197

source

1 指定要序列化的字段(数据表中字段)
publish = serializers.CharField(source='publish.city') # 拿到出版社所在的城市

2 用的最多:只有一个字段(也可以跨表)

SerializerMethodField

1 用的最多:跨表查((来定制返回的字段)要么是列表,要么是字典)
publish=serializers.SerializerMethodField()
def get_publish(self,obj):
       print(obj)
       # return {'name':'sss','city':'sss'}
       return {'name':obj.publish.name,'city':obj.publish.city,'email': obj.publish.email}

image-20210413152323838

在模型表中写方法

# models.py 表模型中写的
def publish_name(self):
  return {'name':self.publish.name,'city':self.publish.city}

@property
def author_list(self):  # 列表推导式
  return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]

# serializers.py 序列化类中
class BookSerializer(serializers.Serializer):
   name = serializers.CharField()
   price = serializers.IntegerField()

   publish_name = serializers.DictField()
   author_list = serializers.ListField()

image-20210413153720618

注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。

常用字段类型

image-20210413155345822

image-20210413155409187

 

标签:请求,self,request,REST,Django,接口,序列化,name
来源: https://www.cnblogs.com/gfeng/p/14653671.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有