基于Django实现 RESTful API 之RestFramework框架1

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 一、首先什么是RESTfulREST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资...

一、首先什么是RESTful

  • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
  • REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
  • 所有的数据,不管是通过网络获取的还是操作数据库获得(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
  • 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构ROA:Resource Oriented Architecture)
  • 对互联网上的任意东西都可视为资源,他认为一个url就是一个资源 比如:http://www.xxx.com/get_user/

二、资源与URI

  • REST全称是表述性状态转移,那究竟指的是什么的表述? 其实指的就是资源。任何事物,只要有被引用到的必要,它就是一个资源。
  • 要让一个资源可以被识别,需要有个唯一标识,在Web中这个唯一标识就是URI(Uniform Resource Identifier)。
  • URI既可以看成是资源的地址,也可以看成是资源的名称。如果某些信息没有使用URI来表示,那它就不能算是一个资源, 只能算是资源的一些信息而已。URI的设计应该遵循可寻址性原则,具有自描述性,需要在形式上给人以直觉上的关联。
URI设计上的一些技巧:
  • 使用_或-来让URI可读性更好
  • 使用/来表示资源的层级关系
  • 使用?用来过滤资源
  • ,或;可以用来表示同级资源的关系

三、什么是API

API就是接口,提供的url。接口有两个用途:

  • 为别人提供服务
  • 前后端分离,一个写vue,一个写后端,他们之间都是通过ajax请求

四、RESTful API设计

  • 网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备......)。

  • 因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。这导致API构架的流行,甚至出现"API First"的设计思想。RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。

关于URL的设计大都长篇大论,这里我就不一一赘述了,通过一个简单的示例来说明,可能有不太符合的地,但是万变理解其宗就好。
  • 首先:http协议请求方式:GET、POST、DELETE、PUT、PATCH、OPTION、HEAD、TRACE
  • 之前URL的设计大多都是这种类型,不符合RESTful规范:
127.0.0.1:8000/books              //查
127.0.0.1:8000/books/add          //增
127.0.0.1:8000/books/change/1     //改
127.0.0.1:8000/books/delete/1     //删
  • 符合RESTful规范的URL设计:
GET请求查看数据:
127.0.0.1:8000/books 
返回所有数据列表 :[{}, {}, {}]

GET请求查看单条数据:
127.0.0.1:8000/books/1 
返回查看的单条数据{}

POST请求添加数据:
127.0.0.1:8000/books 
返回添加数据 :{}

PUT请求更新pk = 1的数据:
127.0.0.1:8000/books/1 
返回更新后的数据: {}

Delete请求删除pk = 1的数据:
127.0.0.1:8000/books/1 
返回空

五、基于Django实现API之RestFramework框架

- RestFramework框架:基于Django帮助我们快速开发符合RESTful规范的接口框架。
- Django实现的API许多功能都需要我们自己开发,未免太过麻烦,这时候Django restframework就给我们提供了方便,直接基于它来返回数据,总之原理都是一样的,就是给一个接口也就是url,让前端的人去请求这个url去获取数据,在页面上显示出来。这样也就达到了前后端分离的效果。下面我们来看看基于Django Rest Framework框架。
  • 首先下载Django Rest Framework,
    pip3 install djangorestframework
Rest Framework框架大体上分为以下十部分内容:
  • (1) APIView
  • (2) 解析器组件
  • (3) 序列化组件
  • (4) 视图类(mixin)
  • (5) 认证组件
  • (6) 权限组件
  • (7) 频率组件
  • (8) 分页组件
  • (9) 响应器组件
  • (10) url注册器

五|1 - APIView:

APIView的源码执行可以参考DjangoCBV的源码执行逻辑

一张图了解一下APIView的源码执行流程吧:
img_38c94992d56a8425eeca76fc92b41c0f.png
6_副本.png

五|2- 解析器组件

对请求的数据进行解析:是针对请求体进行解析的。表示服务器可以解析的数据格式的种类

先来看Django中的发送请求:

- view.py中post请求的执行体:
img_027e053968be4929983be427bebf9693.png
2.png
- 如果是这样的格式发送的数据,在POST里面有值

Content-Type: application/url-encoding..... //数据格式
request.body # 请求体中的原生数据
request.POST

img_f0d6b5ced41aaa343e7ba8ab61916f2e.png
1.png
- 如果是发送的json的格式,在POST里面是没有值的,在body里面有值,可通过decode,然后loads取值

Content-Type: application/json..... //数据格式
request.body # 请求体中的原生数据
request.POST

img_72cd0e9abb74975d1506b32b8a365c98.png
3.png

这种情况下每次都要decode(解码),loads(反序列化),真的很麻烦,所以才有的解析器组件。弥补了django的缺点。

接下来我们先了解restframework的解析器使用方法:

  • 1、可以在CBV试图类中添加属性:
    parser_classes = [JSONParser/FormParser/....] #表示服务器可以解析的数据格式的种类
  • 2、可以在sittings配置项中添加(当然也可以在内置的settings文件中配置)django其实有两个settings文件:
需要用什么数据格式就添加什么数据格式
REST_FRAMEWORK={
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
    ),
}

-3、如果都没有配置的话那就使用默认的配置:

    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    )

看到这可能就懵逼了,不过没关系,这几种方法其实都是因为分析了源码之后得出的,下面就一起来分析一下源码的执行流程吧:

步骤一、先来看看Django RestFramework的发送请求:(和Django的对比发现不同)

- view.py中post请求的执行体:
img_c7dfacd860e2f198cfa16c6809a8a272.png
4.png
- 如果是这样的格式发送的数据,在POST里面有值

Content-Type: application/url-encoding..... //数据格式
request.body # 请求体中的原生数据
request.POST
request.data #reqest.data是APIView重装request才有的,reqest.data取值的时候才执行解析器组件

img_d8a6f59ae4ae046628f70c708157dd75.png
5.png

- 如果是发送的json的格式,在POST里面是没有值的,在body里面有值,可通过decode,然后loads取值

Content-Type: application/json..... //数据格式
request.body # 请求体中的原生数据
request.POST
request.data #reqest.data是APIView重装request才有的,reqest.data取值的时候才执行解析器组件

img_5fde335cf6c56ec9fda5b253388b5e63.png
6.png

步骤二、解析器源码执行流程:

img_68fd6ffbdafc38727f517d9f87b1df69.jpe
解析器源码执行流程.jpg

五|3- 序列化组件

- 首先表结构:models.py
from django.db import models

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()

    def __str__(self):
        return self.name

class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

    def __str__(self):
        return self.name

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)

    # 与Publish建立一对多的关系,外键字段建立在多的一方
    publish = models.ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE)
    # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
    authors = models.ManyToManyField(to='Author', )
- 先看一下基于Django的CBV接口设计

缺点:需要自己设计数据格式、需要自己做序列化操作、需要自己讲不支持json序列化的数据类型转化

class Booklist(View):

    def get(self, request):
        book_obj = models.Book.objects.all()
        ret = []
        for obj in book_obj:
            ret.append({
                "title":obj.title,
                "price":"%s"%obj.price,
            })
        return HttpResponse(json.dumps(ret,ensure_ascii=False))
- 基于Django的序列化组件的接口设计

缺点:只支持序列化,而不支持校验、错误提示等附加功能

from django.core.serializers import serialize 

class Booklist(View):

    def get(self, request):
        book_obj = models.Book.objects.all()
        data = serialize("json", book_obj)
        return HttpResponse(data)
- 基于DRF ( Django RestFramework ) Serializer 的接口设计

DRF ( Django RestFramework ) Serializer的序列化方式可以类比Django的Form组件的使用
注意一点:因为Serializer和数据库没有实质上的联系,所以post请求时不能直接保存到数据库

from rest_framework.views import APIView
from app001 import models
# rest_framework重装的response
from rest_framework.response import Response
# 序列化组件的导入
from rest_framework import serializers

class BooklistSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=32)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    publishDate = serializers.DateTimeField()
    # 一对多字段,可以通过source参数取出想要的关联对象的任意字段
    publish_name = serializers.CharField(source="publish.name",read_only=True)
    publish_city = serializers.CharField(source="publish.city",read_only=True)
    # 多对多字段,可以通过source参数取出所有关联对象queryset集合,几乎没用
    # authors = serializers.CharField(max_length=32, source="authors.all",read_only=True)
    # 多对多字段,固定的书写格式
    authors = serializers.SerializerMethodField(read_only=True)
    def get_authors(self, obj):  # 函数命名必须是get_field形式,obj为当前字段对象
        ret = []
        for obj in obj.authors.all():
            ret.append(obj.name)
        return ret

class Booklist(APIView):
    # 查 get
    def get(self, request):
        book_obj = models.Book.objects.all()
        bs = BooklistSerializer(book_obj, many=True)
        data = bs.data  # 序列化接口
        return Response(data)
    #增 post
    def post(self, request):
        print(request.data)  # 静态方法:解析数据工作
        bs = BooklistSerializer(data=request.data)
        if bs.is_valid():  # 校验
            return Response(bs.data)  # 序列化数据
        else:
            return Response(bs.errors)  # 序列化错误信息

- 基于DRF ( Django RestFramework ) ModelSerializer 的接口设计

DRF ( Django RestFramework ) Serializer的序列化方式可以类比Django的ModelForm组件的使用
当涉及到一对多或者多对多字段时,我们可以通过自定制操作来获得我们想要的数据形式,
更多更细相关序列化内容请看:https://www.cnblogs.com/pyspark/p/8607801.html

class BooklistSerializer(serializers.ModelSerializer):

    //serializers.ChoiceField字段也可以通过source="get_字段名_display"的方式取出对应数字的中文简介
    //一对多字段,可以通过source参数取出想要的关联对象的任意字段
    //一对多字段,需要添加read_only=True参数,这个参数在post请求时有用

    publish_name = serializers.CharField(source="publish.name",read_only=True)
    publish_city = serializers.CharField(source="publish.city",read_only=True)

    // 多对多字段,固定的书写格式
    // 函数命名必须是get_field形式,obj为当前字段对象

    authors = serializers.SerializerMethodField()
    def get_authors(self, obj):  
        ret = []
        for obj in obj.authors.all():
            ret.append(obj.name)
        return ret

    class Meta:
        model=models.Book
        fields="__all__"    //指定所有字段
        extra_kwargs={"publish":{"write_only":True},"authors":{"write_only":True}}   //设置post写入的只写不读字段


class Booklist(APIView):

    def get(self, request):
        book_obj = models.Book.objects.all()
        bs = BooklistSerializer(book_obj, many=True)
        data = bs.data  # 序列化接口
        return Response(data)

    def post(self, request):    
        // 静态方法:解析数据工作
        print(request.data) 

        //post请求时不仅仅是序列化了,还需要验证、保存等,必须在实例化时加上data
        //post发送的是添加请求,单个对象many=False
        bs = BooklistSerializer(data=request.data,many=False) 

        // 校验
        if bs.is_valid():  
            bs.save()                            // create操作
            return Response(bs.data)            // 序列化数据
        else:
            return Response(bs.errors)         // 序列化错误信息

强调:API的设计符合RESTful规范(请求方式、url设计、返回数据)

相关文章
|
8天前
|
SQL 缓存 测试技术
构建高性能RESTful API:最佳实践与避坑指南###
—— 本文深入探讨了构建高性能RESTful API的关键技术要点,从设计原则、状态码使用、版本控制到安全性考虑,旨在为开发者提供一套全面的最佳实践框架。通过避免常见的设计陷阱,本文将指导你如何优化API性能,提升用户体验,确保系统的稳定性和可扩展性。 ###
45 12
|
4天前
|
Python
Django 框架的路由系统
Django 框架的路由系统
20 6
|
5天前
|
JSON JavaScript API
深入浅出Node.js:从零开始构建RESTful API
【10月更文挑战第39天】 在数字化时代的浪潮中,API(应用程序编程接口)已成为连接不同软件应用的桥梁。本文将带领读者从零基础出发,逐步深入Node.js的世界,最终实现一个功能完备的RESTful API。通过实践,我们将探索如何利用Node.js的异步特性和强大的生态系统来构建高效、可扩展的服务。准备好迎接代码和概念的碰撞,一起解锁后端开发的新篇章。
|
8天前
|
存储 API 开发者
深入理解RESTful API设计原则
本文探讨了RESTful API的设计原则,强调了其在现代Web服务中的重要性。通过分析状态表示转移(REST)的概念、核心约束以及最佳实践,本文旨在为开发者提供构建高效、可扩展和易于维护的API的指导。文章还讨论了常见的设计陷阱和如何避免它们,以确保API设计的健壮性和灵活性。
|
9天前
|
API PHP 数据库
PHP中哪个框架最适合做API?
在数字化时代,API作为软件应用间通信的桥梁至关重要。本文探讨了PHP中适合API开发的主流框架,包括Laravel、Symfony、Lumen、Slim、Yii和Phalcon,分析了它们的特点和优势,帮助开发者选择合适的框架,提高开发效率、保证接口稳定性和安全性。
26 3
|
9天前
|
JSON 缓存 API
构建高效RESTful API的最佳实践
【10月更文挑战第34天】在数字时代的浪潮中,后端开发扮演着至关重要的角色。本文将带你深入探索如何构建高效的RESTful API,从设计原则到实际编码技巧,再到性能优化和错误处理,我们将一一解锁这些技能。你将学会如何打造一个既优雅又强大的后端服务,让你的应用程序在激烈的市场竞争中脱颖而出。那么,让我们一起踏上这段精彩的旅程吧!
25 2
|
8天前
|
安全 API 网络架构
Python中哪个框架最适合做API?
本文介绍了Python生态系统中几个流行的API框架,包括Flask、FastAPI、Django Rest Framework(DRF)、Falcon和Tornado。每个框架都有其独特的优势和适用场景。Flask轻量灵活,适合小型项目;FastAPI高性能且自动生成文档,适合需要高吞吐量的API;DRF功能强大,适合复杂应用;Falcon高性能低延迟,适合快速API开发;Tornado异步非阻塞,适合高并发场景。文章通过示例代码和优缺点分析,帮助开发者根据项目需求选择合适的框架。
27 0
|
8天前
|
JavaScript 前端开发 NoSQL
深入浅出:使用Node.js构建RESTful API
【10月更文挑战第35天】在数字时代的浪潮中,后端技术如同海洋中稳固的灯塔,为前端应用提供数据和逻辑支撑。本文旨在通过浅显易懂的方式,带领读者了解如何利用Node.js这一强大的后端平台,搭建一个高效、可靠的RESTful API。我们将从基础概念入手,逐步深入到代码实践,最终实现一个简单的API示例。这不仅是对技术的探索,也是对知识传递方式的一次创新尝试。让我们一起启航,探索Node.js的奥秘,解锁后端开发的无限可能。
|
5天前
|
JSON API 数据格式
淘宝 / 天猫官方商品 / 订单订单 API 接口丨商品上传接口对接步骤
要对接淘宝/天猫官方商品或订单API,需先注册淘宝开放平台账号,创建应用获取App Key和App Secret。之后,详细阅读API文档,了解接口功能及权限要求,编写认证、构建请求、发送请求和处理响应的代码。最后,在沙箱环境中测试与调试,确保API调用的正确性和稳定性。
|
17天前
|
供应链 数据挖掘 API
电商API接口介绍——sku接口概述
商品SKU(Stock Keeping Unit)接口是电商API接口中的一种,专门用于获取商品的SKU信息。SKU是库存量单位,用于区分同一商品的不同规格、颜色、尺寸等属性。通过商品SKU接口,开发者可以获取商品的SKU列表、SKU属性、库存数量等详细信息。