1.内容回顾
    1.restframework serializer(序列化)的简单使用
        
        QuereySet([obj,obj,obj])  -->  JSON格式数据
        
    安装和导入:
        pip install djangorestframework
        
        from rest_framework import serializer
        
        1.创建一个类,类一定要继承serializer.Serializers
        
        2.chocie字段和FK字段都可以通过source来获取对应的值
        
        3.多对多字段可以通过使用serializer.SerializerMethod
    
                声明序列化器:
                def get_tag(self, obj):
                    tag_list = []
                    for i in obj.tag.all():
                        tag_list.append(i.name)
                    return tag_list
                    (比较麻烦)
        2.使用 ModelSerializer(简单)
        和ORM绑定的序列化
            通过配置class Meta:
                        model = 表名
                        fields = ['字段', ...]
                        depth = 1
                        
2. 今日内容
    1. RESTful风格API介绍

一、什么是RESTful

REST -- REpresentational State Transfer,英语的直译就是“表现层状态转移”。如果看这个概念,估计没几个人能明白是什么意思。
那下面就让我来用一句人话解释一下什么是RESTful:URL定位资源,用HTTP动词(GET,POST,PUT,DELETE)描述操作。

Resource:资源,即数据。

Representational:某种表现形式,比如用JSON,XML,JPEG等;

State Transfer:状态变化。通过HTTP动词实现。

REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”。

REST从资源得角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态。

所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性。

二、RESTful API设计

API与用户的通信协议

总是使用HTTPs协议域名

https://api.example.com        尽量将API部署在专用域名

https://example.org/api/       API很简单

版本

1.  将版本信息放在URL中,如:https://api.example.com/v1/

2. 将版本信息放在请求头中。

路径

视网络上任何东西都是资源,均使用名词表示(可复数)

https://api.example.com/v1/zoos

https://api.example.com/v1/animals

https://api.example.com/v1/employees

method

GET      :从服务器取出资源(一项或多项)

POST    :在服务器新建一个资源

PUT      :在服务器更新资源(客户端提供改变后的完整资源)

PATCH  :在服务器更新资源(客户端提供改变的属性)

DELETE :从服务器删除资源

过滤

通过在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:指定筛选条件

状态码

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://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
错误处理 状态码是4xx时,应返回错误信息,error当做key。     {
error: "Invalid API key"
}
返回结果 针对不同操作,服务器向用户返回的结果应该符合以下规范 GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 PATCH /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档
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

 1.RESTful API之url设计

路由分发:

在原先的URL中添加:url(r'api/', include(app01_urls)),  include表示导入py文件

在 app01下新建路径文件:app01_urls.py

from django.conf.urls import urlfrom app01 import views

urlpatterns = [

url(r'article/', views.Article.as_view()),

url(r'article/(?P<pk>\d+)', views.ArticleDetail.as_view(), name='article-detail'),

url(r'school/(?P<id>\d+)', views.SchoolDetail.as_view(), name='school-detail111'),

# 评论

# url(r'comment_list/', ),

# url(r'add_comment/', ),

# url(r'delete_comment/', ),

# url(r'edit_comment/', ),

url(r'comment/', views.Comment.as_view()),

]

2.RESTful API之urls视图

针对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 viewsclass 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

from rest_framework import APIView  
 class Comment(views.View):

   pass

--------  之前的写法 ↑  ----------

class APIView(views.View):

扩展的功能

self.request = Resquest(

self._request = request(Django的request)

)

self.request.data  封装好的数据属性,POST\PUT请求携带的数据都可以从这里取

pass

  class Comment(APIView):

pass

1. APIView与View的区别

  1. APIView是View的子类
  2. 传递给请求处理程序的request实例是REST框架的请求实例,而不是Django的HttpRequest实例
  3. 处理程序返回的基于REST框架的Response,而不是Django的HttpResponse,视图函数将会管理内容协商,然后设置正确的渲染方式
  4. 任何APIException将会被捕捉,然后转换成合适的response对象
  5. 接收到的请求首先被认证,然后赋予相应的权限,然后通过节流器分发给相应的请求处理函数,类似.get()和.post()

APIView是专门写API的视图函数,结合serializers,非常方便做序列化!

关于APIView的源码解析,请参考文章:

https://blog.csdn.net/u013210620/article/details/79857654

取数据

get:

  request._request ( 原request )

  request.GET == request._request.GET

post:

  request.data ( 得到 json 数据,也可得到 urlencode 数据)

    都是 rest_framework  APIView 的功劳,

  如果使用 View , request.post( 只能得到 urlencode 的数据,不能得到 json 数据,只能从 request.body 中取)

3. serializer
        1. ModelSerializer
            1. 基于APIView实现的GET和POST

    2. POST过来的数据进行校验
            3. 保存数据

在app01下面创建一个文件,专门放序列化的

from app01.models import Comment, Article, School

from rest_framework import serializers

from rest_framework.validators import ValidationError

 # 序列化评论的类
  class CommentSerializer(serializers.ModelSerializer): # content = serializers.CharField(error_messages={"required": '内容不能为空'}) # article_detail = serializers.SerializerMethodField(read_only=True) # 用于做校验的钩子函数,类似于form组件的clean_字段名 def validate_content(self, value):
if '草' in value:
raise ValidationError('不符合社会主义核心价值观!')
else:
return value # 全局的钩子
# def validate(self, attrs):
# # self.validated_data # 经过校验的数据 类似于form组件中的cleaned_data
# # 全局钩子
# pass class Meta: model = Comment
fields = "__all__"
# depth = 1 # 定义额外的参数
extra_kwargs = {
"content": {
"error_messages": {
"required": '内容不能为空',
}
}, "article": {
"error_messages": {
"required": '文章不能为空'
}
}
} # 文章的序列化类
  class ArticleModelSerializer(serializers.ModelSerializer): # type_str = serializers.CharField(source='get_type_display', read_only=True) class Meta: model = Article # 绑定的ORM类是哪一个 fields = "__all__" # ["id", "title", "type"] # depth = 1 # 官方推荐不超过10层 # 文章超链接序列化 class ArticleHyperLinkedSerializer(serializers.HyperlinkedModelSerializer): school = serializers.HyperlinkedIdentityField(view_name='school-detail111', lookup_url_kwarg='id') class Meta: model = Article # 绑定的ORM类是哪一个 fields = ["id", "title", "type", "school"] # 学校的序列化 class SchoolSerializer(serializers.ModelSerializer): class Meta: model = School fields = "__all__" 参数解释: source 表示来源 lookup_field 表示查找字段 lookup_url_kwarg 表示路由查找的参数,pk表示主键 view_name 它是指urls定义的name值,一定要一一对应。

models.py

from django.db import models

# 文章表
class Article(models.Model):
    title = models.CharField(max_length=32, unique=True, error_messages={"unique": "文章标题不能重复"})
    # 文章发布时间
    # auto_now每次更新的时候会把当前时间保存
    create_time = models.DateField(auto_now_add=True)
    # auto_now_add 第一次创建的时候把当前时间保存
    update_time = models.DateField(auto_now=True)
    # 文章的类型
    type = models.SmallIntegerField(
        choices=((1, "原创"), (2, "转载")),
        default=1
    )
    # 来源
    school = models.ForeignKey(to='School', on_delete=models.CASCADE)
    # 标签
    tag = models.ManyToManyField(to='Tag')

# 文章来源表
class School(models.Model):
    name = models.CharField(max_length=16)

# 文章标签表
class Tag(models.Model):
    name = models.CharField(max_length=16)

# 评论表
class Comment(models.Model):
    content = models.CharField(max_length=128)
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE)


GET:
class Comment(APIView):

def get(self, request):

res = {"code": 0}

# print(self.request)  # rest framework封装好的request

# print(self.request.data)

# print(self.request._request.GET.get("age"))  # Django原来的request对象

# 数据

all_comment = models.Comment.objects.all()

# 序列化

ser_obj = app01_serializers.CommentSerializer(all_comment, many=True)

res["data"] = ser_obj.data

return Response(res)

POST:
def post(self, request):
    res = {"code": 0}
    # 去提交的数据
    comment_data = self.request.data
    # 对用户提交的数据做校验
    ser_obj = app01_serializers.CommentSerializer(data=comment_data)
    if ser_obj.is_valid():
        # 表示数据没问题,可以创建
        ser_obj.save()  #创建数据,写入数据库
    else:
        # 表示数据有问题
        res["code"] = 1
        res["error"] = ser_obj.errors
    return Response(res)

return HttpResponse("创建新评论")

#文章CBV
class Article(APIView):
  def get(self,request):
    res={"code":0}
    all_article = models.Article.object.all()                        #显示超链接的URL需要的参数,表示上下文
    ser_obj = app01_serializers.ArticleHyperLinkedSerializer(all_article, many=True, context={'request': request})
    res["data"] = ser_obj.data
      return Response(res)

  def post(self, request):
      res = {"code": 0}
      ser_obj = app01_serializers.ArticleModelSerializer(data=self.request.data)
      if ser_obj.is_valid():
          ser_obj.save()
      else:
          res["code"] = 1
          res["error"] = ser_obj.errors
      return Response(res)

# 文章详情CBV
class ArticleDetail(APIView):
    def get(self, request, pk):
        res = {"code": 0}
        article_obj = models.Article.objects.filter(pk=pk).first()
        # 序列化
        ser_obj = app01_serializers.ArticleHyperLinkedSerializer(article_obj, context={'request': request})
        res["data"] = ser_obj.data
        return Response(res)


# 学校详情CBV
class SchoolDetail(APIView):
    def get(self, request, id):
        res = {"code": 0}
        school_obj = models.School.objects.filter(pk=id).first()
        ser_obj = app01_serializers.SchoolSerializer(school_obj, context={'request': request})
        res["data"] = ser_obj.data
        return Response(res)

Response: 

配置之后:浏览器才可访问; rest_framework 是django的一个app!

可发 get / post 请求 !!

rest framework 引入了Response对象,它是一个TemplateResponse类型,并根据客户端需求正确返回需要的类型。

使用前,需要导入模块

from rest_framework.response import Response

语法:

return Response(data) # 根据客户端的需求返回不同的类型。

0801 RESTAPI设计,DRF 序列化的更多相关文章

  1. python 全栈开发,Day95(RESTful API介绍,基于Django实现RESTful API,DRF 序列化)

    昨日内容回顾 1. rest framework serializer(序列化)的简单使用 QuerySet([ obj, obj, obj]) --> JSON格式数据 0. 安装和导入: p ...

  2. 揭开DRF序列化技术的神秘面纱

    在RESTful API中,接口返回的是JSON,JSON的内容对应的是数据库中的数据,DRF是通过序列化(Serialization)的技术,把数据模型转换为JSON的,反之,叫做反序列化(dese ...

  3. DRF 序列化组件

    Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...

  4. python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  5. Django的DRF序列化方法

    安装rest_framework -- pip install djangorestframework -- 注册rest_framework序列化 -- Python--json -- 第一版 用v ...

  6. drf序列化器与反序列化

    什么是序列化与反序列化 """ 序列化:对象转换为字符串用于传输 反序列化:字符串转换为对象用于使用 """ drf序列化与反序列化 &qu ...

  7. drf序列化及反序列化

    假如把drf看做一个汉堡包,我们之前讲的模块属于汉堡包前面的盖盖(请求模块.渲染模块)和底底(异常模块.解析模块.响应模块),但是真正中间的夹心没有讲,那么今天我就和大家来看一下汉堡包的夹心(序列化及 ...

  8. drf序列化和反序列化

    目录 drf序列化和反序列化 一.自定义序列化 1.1 设置国际化 二.通过视图类的序列化和反序列化 三.ModelSerializer类实现序列化和反序列化 drf序列化和反序列化 一.自定义序列化 ...

  9. DRF 序列化组件 模型层中参数补充

    一. DRF序列化 django自带有序列化组件,但是相比rest_framework的序列化较差,所以这就不提django自带的序列化组件了. 首先rest_framework的序列化组件使用同fr ...

随机推荐

  1. linux 分卷压缩命令

    linux 分卷压缩命令 1.使用tar分卷压缩 格式 tar cvzf - filedir | split -d -b 50m - filename 样例: tar cvzf - ./picture ...

  2. 关于dll的pdb文件的小贴士

    .pdb文件最好与生成它的.dll文件放在一起,这样调试的时候才有可能跟踪进dll的内部函数里.

  3. C++ 虚析构(virtual destructor)原理

    注意:本文仅为个人理解,可能有误! 先看一段代码: #include <iostream> using namespace std; class CBase{ public: CBase( ...

  4. PHP和Java 加解密

    http://www.jb51.net/article/64961.htm http://www.jb51.net/article/129218.htm http://www.jb51.net/art ...

  5. A guide to analyzing Python performance

    来源:http://www.huyng.com/posts/python-performance-analysis/ While it's not always the case that every ...

  6. iOS学习笔记(一)——ios搭建开发环境

    好久就想试水IOS开发了,由于开发环境限制,一直局限于理论和虚拟机,近来入手了MacBook Pro,也来尝尝鲜,笔者也是现学现总结,如果有不足,请指正. IOS开发必备MAC OS X 另加一部iP ...

  7. NoSQL-MongoDB with python

    前言: MongoDB,文档存储型数据库(document store).NoSQL数据库中,它独占鳌头,碾压其他的NoSQL数据库. 使用C++开发的,性能仅次C.与redis一样,开源.高扩展.高 ...

  8. 【BZOJ1811】[Ioi2005]mea 乱搞

    [BZOJ1811][Ioi2005]mea Description 考虑一个非递减的整数序列 S1,....Sn+1(Si<=Si+1 1<=i<=n). 序列M1...Mn是定义 ...

  9. EasyNVR摄像机无插件直播按需RTSP拉流播放流程详解

    1.背景需求 有许多客户现场,有许多设备但是不需要一直向设备端取视频流,因为在用户不观看的情况下,还在获取视频资源,一方面大大的浪费了网络带宽资源,一方面对设备服务器要求也较高,用户成本就要提高,这是 ...

  10. ActiveMQ5.10.2版本配置JMX

    ActiveMQ的特性之一是很好的支持JMX.通过JMX MBeans可以很方便的监听和控制ActiveMQ的broker. 鉴于官方网站提供的JMX特性说明对于远程访问的配置流程不是很完整,笔者在实 ...