【Django-DRF】多年积累md笔记 0基础到高手. 第(3)篇:使用Django开发REST接口

举报
程序员一诺112 发表于 2023/10/31 21:15:51 2023/10/31
【摘要】 本文从分析现在流行的前后端分离Web应用模式说起,然后介绍如何设计REST API,通过使用Django来实现一个REST API为例,明确后端开发REST API要做的最核心工作,然后介绍Django REST framework能帮助我们简化开发REST API的工作。

本文从分析现在流行的前后端分离Web应用模式说起,然后介绍如何设计REST API,通过使用Django来实现一个REST API为例,明确后端开发REST API要做的最核心工作,然后介绍Django REST framework能帮助我们简化开发REST API的工作。


完整版笔记直接地址: 请移步这里



共 5 章,24 子模块,总计1.7w+ 字





引入Django REST framework


在本章中,我们要大家介绍为什么学习Django REST framework,它能帮助我们做哪些事情。

课 程思路

我们从分析现在流行的前后端分离Web应用模式说起,然后介绍如何设计REST API,通过使用Django来实现一个REST API为例,明确后端开发REST API要做的最核心工作,然后介绍Django REST framework能帮助我们简化开发REST API的工作。



使用Django开发REST 接口


我们以在Django框架中使用的图书英雄案例来写一套支持图书数据增删改查的REST API接口,来理解REST API的开发。

在此案例中,前后端均发送JSON格式数据。


# views.py


from datetime import datetime
​
class BookListView(View):
    """
    查询所有图书、增加图书
    """
    def get(self, request):
        """
        查询所有图书
        路由:GET /books/
        """
        queryset = BookInfo.objects.all()
        book_list = []
        for book in queryset:
            book_list.append({
                'id': book.id,
                'btitle': book.btitle,
                'bpub_date': book.bpub_date,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'image': book.image.url if book.image else ''
            })
        return JsonResponse(book_list, safe=False)
​
    def post(self, request):
        """
        新增图书
        路由:POST /books/
        """
        json_bytes = request.body
        json_str = json_bytes.decode()
        book_dict = json.loads(json_str)
​
        # 此处详细的校验参数省
​
        book = BookInfo.objects.create(
            btitle=book_dict.get('btitle'),
            bpub_date=book_dict.get('bpub_date')
        )
​
        return JsonResponse({
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
            'image': book.image.url if book.image else ''
        }, status=201)


 class BookDetailView(View):
•        def get(self, request, pk):
•            """
•            单个图书信息
•            路由: GET  /books/<pk>/
•            """
•            try:
•                book = BookInfo.objects.get(pk=pk)
•            except BookInfo.DoesNotExist:
•                return HttpResponse(status=404)
•    
•            return JsonResponse({
•                'id': book.id,
•                'btitle': book.btitle,
•                'bpub_date': book.bpub_date,
•                'bread': book.bread,
•                'bcomment': book.bcomment,
•                'image': book.image.url if book.image else ''
•            })
•    
        def put(self, request, pk):
            """
            修改图书信息
            路由: PUT  /books/<pk>
            """
            try:
                book = BookInfo.objects.get(pk=pk)
            except BookInfo.DoesNotExist:
                return HttpResponse(status=404)    


        json_bytes = request.body
        json_str = json_bytes.decode()
        book_dict = json.loads(json_str)


   # 此处详细的校验参数省略


        book.btitle = book_dict.get('btitle')
        book.bpub_date = book_dict.get('bpub_date')
        book.save()
​
        return JsonResponse({
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
            'image': book.image.url if book.image else ''
        })
​
    def delete(self, request, pk):
        """
        删除图书
        路由: DELETE /books/<pk>/
        """
        try:
            book = BookInfo.objects.get(pk=pk)
        except BookInfo.DoesNotExist:
            return HttpResponse(status=404)
​
        book.delete()
​
        return HttpResponse(status=204)


# urls.py


urlpatterns = [
    url(r'^books/$', views.BookListView.as_view()),
    url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view())
]


测试


使用Postman测试上述接口

1) 所有图书数据

GET 方式访问

127.0.0.1:8000/books/

返回状态码200,数据如下

[
•        {
•            "id": 1,
•            "btitle": "射雕英雄传",
•            "bpub_date": "1980-05-01",
•            "bread": 12,
•            "bcomment": 34,
•            "image": ""
•        },
•        {
•            "id": 2,
•            "btitle": "天龙八部",
•            "bpub_date": "1986-07-24",
•            "bread": 36,
•            "bcomment": 40,
•            "image": ""
•        },
•        {
•            "id": 3,
•            "btitle": "笑傲江湖",
•            "bpub_date": "1995-12-24",
•            "bread": 20,
•            "bcomment": 80,
•            "image": ""
•        },
•        {
•            "id": 4,
•            "btitle": "雪山飞狐",
•            "bpub_date": "1987-11-11",
•            "bread": 58,
•            "bcomment": 24,
•            "image": ""
•        },
•        {
•            "id": 5,
•            "btitle": "西游记",
•            "bpub_date": "1988-01-01",
•            "bread": 10,
•            "bcomment": 10,
•            "image": "booktest/xiyouji.png"
•        },
•        {
•            "id": 6,
•            "btitle": "水浒传",
•            "bpub_date": "1992-01-01",
•            "bread": 10,
•            "bcomment": 11,
•            "image": ""
•        },
•        {
•            "id": 7,
•            "btitle": "红楼梦",
•            "bpub_date": "1990-01-01",
•            "bread": 0,
•            "bcomment": 0,
•            "image": ""
•        }
•    ]


2)单一图书数据

GET 访问 127.0.0.1:8000/books/5/,返回状态码200, 数据如下

{
•        "id": 5,
•        "btitle": "西游记",
•        "bpub_date": "1988-01-01",
•        "bread": 10,
•        "bcomment": 10,
•        "image": "booktest/xiyouji.png"
•    }



GET 访问 127.0.0.1:8000/books/100/,返回状态码404

3)新增图书数据

POST 访问 127.0.0.1:8000/books/,发送JSON数据

{ ​ "btitle": "三国演义", ​ "bpub_date": "1990-02-03" ​ }

返回状态码201,数据如下

​ { ​ "id": 8, ​ "btitle": "三国演义", ​ "bpub_date": "1990-02-03", ​ "bread": 0, ​ "bcomment": 0, ​ "image": "" ​ }

4)修改图书数据

PUT 访问 127.0.0.1:8000/books/8/,发送JSON数据

​ { ​ "btitle": "三国演义(第二版)", ​ "bpub_date": "1990-02-03" ​ }

返回状态码200,数据如下


{
    "id": 8,
    "btitle": "三国演义(第二版)",

"bpub_date": "1990-02-03", ​ "bread": 0, ​ "bcomment": 0, ​ "image": "" ​ }

5)删除图书数据

DELETE 访问 127.0.0.1:8000/books/8/,返回204状态码




明确REST接口开发的核心任务


分析一下上节的案例,可以发现,在开发REST API接口时,视图中做的最主要有三件事:

  • 将请求的数据(如JSON格式)转换为模型类对象

  • 操作数据库

  • 将模型类对象转换为响应的数据(如JSON格式)


序列化Serialization


维基百科中对于序列化的定义:

列化(serialization)在计算机科学的资料处理中,是指将数据结构或物件状态转换成可取用格式(例如存成档案,存于缓冲,或经由网络中传送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。依照序列化格式重新字节的结果时,可以利用它来产生与原始物件相同语义的副本。对于许多物件,像是使用大量参照的复杂物件,这种序列化重建的过程并不容易。面向对象中的物件序列化,并不概括之前原始物件所关联的函式。这种过程也称为物件编组(marshalling)。从一系列字节提取数据结构的反向操作,是反序列化(也称为解编组, deserialization, unmarshalling)。

序 列化在计算机科学中通常有以下定义:

在数据储存与传送的部分是指将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等,或者透过网络传送资料时进行编码的过程,可以是字节或是XML等格式。而字节的或XML编码格式可以还原完全相等的对象。这程序被应用在不同应用程序之间传送对象,以及服务器将对象储存到档案或数据库。相反的过程又称为反序列化

简而言之,我们可以将 序 列化理解为:将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等),例如将Django中的模型类对象装换为JSON字符串,这个转换过程我们称为序列化。

如:

​ queryset = BookInfo.objects.all() ​ book_list = []


# 序列化




for book in queryset:
    book_list.append({
        'id': book.id,
        'btitle': book.btitle,
        'bpub_date': book.bpub_date,
        'bread': book.bread,
        'bcomment': book.bcomment,
        'image': book.image.url if book.image else ''
    })
return JsonResponse(book_list, safe=False)

反 之,将其他格式(字典、JSON、XML等)转换为程序中的数据,例如将JSON字符串转换为Django中的模型类对象,这个过程我们称为反序列化。

如:

​ json_bytes = request.body ​ json_str = json_bytes.decode()


# 反序列化




book_dict = json.loads(json_str)
book = BookInfo.objects.create(
    btitle=book_dict.get('btitle'),
    bpub_date=book_dict.get('bpub_date')
)

我们可以看到, 在 开发REST API时,视图中要频繁的进行序列化与反序列化的编写。


总结


在开发REST API接口时,我们在 视 图中需要做的最核心的事是:

  • 将 数据库数据序列化为前端所需要的格式,并返回;

  • 将 前端发送的数据反序列化为模型类对象,并保存到数据库中。




未完待续 下一期 下一篇


完整笔记请看文章开头

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。