分享

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

 程序员一诺 2023-10-31 发布于北京

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

# 完整版笔记直接地址: [请移步这里](https:///yinuo112/backend/blob/master/django/django-DRF知识点大集合共5大模块/django-DRF知识点大集合共5大模块.md)

---

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

![](https://it-res-md-1300471212.cos.ap-beijing./blog_md/images/django-DRF知识点大集合共5大模块/0.jpg)

![](https://it-res-md-1300471212.cos.ap-beijing./blog_md/images/django-DRF知识点大集合共5大模块/2.jpg)

---

# 引入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)

```python

 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,数据如下

  ```json  

[

        {

            "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, 数据如下

```json

{

        "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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多