0
点赞
收藏
分享

微信扫一扫

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

本文从分析现在流行的前后端分离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接口时,我们在 视 图中需要做的最核心的事是:

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

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

未完待续 下一期 下一篇

完整笔记请看文章开头

举报

相关推荐

0 条评论