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

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

时间:2023-10-31 21:31:59浏览次数:36  
标签:md bpub btitle image REST Django book date bread

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

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

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

未完待续 下一期 下一篇

完整笔记请看文章开头

标签:md,bpub,btitle,image,REST,Django,book,date,bread
From: https://blog.51cto.com/u_13578013/8114371

相关文章

  • 关于有很多好题写了但是不知道放哪所以就放在同一个博客里了md这标题怎么这么长这件事
    不分难度.我只是想把一些好玩或者有思维含量的题塞进来.InversionCounting我是不会告诉你其实我是因为这题标签有平衡树才做的.这题标签有平衡树.但是并不需要平衡树.这题操作时在反转区间嘛,然后求逆序对.容易发现,实际上有变化的逆序对只有完全在这个区间内的.换句话说,......
  • lamdba表达式
    lamdba表达式是为了避免匿名内部类定义过多为什么要使用lambda表达式避免匿名内部类定义过多可以让你的代码看起来很简洁去掉了一堆没有意义的代码,只留下核心的逻辑。packagecom.xh.Thread;/***lamdba表达式事实上是内部接口**/publicclassLamdbaTest{ //3,定义一......
  • 软件测试|Django 入门:构建Python Web应用的全面指南
    引言Django是一个强大的PythonWeb框架,它以快速开发和高度可扩展性而闻名。本文将带您深入了解Django的基本概念和核心功能,帮助您从零开始构建一个简单的Web应用。什么是Django?Django是一个基于MVC(模型-视图-控制器)设计模式的Web框架,旨在简化Web应用程序的开发过程。它由Dja......
  • 【CVPR2023】Efficient and Explicit Modelling of Image Hierarchies for Image Rest
    >论文:https://readpaper.com/paper/4728855966703960065代码:https://github.com/ofsoundof/GRL-Image-Restoration这个论文的代码地址叫GRL,意思是Global,Regional,Local的意思,作者从三个尺度对特征建模,核心是构建了一个anchoredstripself-attention。如何从Global,R......
  • [BJDCTF2020]Easy MD5
    打开题目,发现是一个输入框,抓响应包后发现存在如下提示:Hint:select*from'admin'wherepassword=md5($pass,true)。当PHP的md5()函数的第二个参数为True时,会将string转换为16字符的二进制格式,如使用一些特殊的$pass,则可以绕过以上SQL查询,如:ffifdyop,ffifdyop计算......
  • systemd中的slice服务单元
    使用场景对一组服务进行管理,比如限制资源使用、调整启动顺序和依赖关系。比如,好几个服务都需要限制内存使用,可以每个服务都加个MemoryLimit=373741824,也可以将这些服务加入到同一个slice,然后,只需要在slice中配置MemoryLimit=373741824。介绍systemd的slice是一种服务单元,用......
  • [CF566E] Restoring Map
    RestoringMap星空蚁来了秒了。人与人的智力是有差距的。刷再多的CF智力不行就是不行。OI这种需要智力的游戏不适合我。我还是更适合对智力要求低一点的。比如和妹子贴贴。但是也没有妹子。lifeishard.这类树的构造似乎可以从边缘情况想起,比如CF1844G但是这个题从叶......
  • [CF566E]Restoring Map
    题目描述ArchaeologistsfoundsomeinformationaboutanancientlandofTreeland.WeknowforsurethattheTreelandconsistedof$n$citiesconnectedbythe$n-1$road,suchthatyoucangetfromeachcitytoanyotheronealongtheroads.However,thei......
  • K8s:Pod 中 command、args 与 Dockerfile 中 CMD、 ENTRYPOINT 的对应关系
    写在前面前几天被问到,这里整理笔记之前也没怎么注意这个问题理解不足小伙伴帮忙指正曾以为老去是很遥远的事,突然发现年轻是很久以前的事了。时光好不经用,抬眼已是半生,所谓的中年危机,真正让人焦虑的不是孤单、不是贫穷、更不是衰老,而是人到中年你才发现,你从来没有按照自己喜欢的方......
  • PostgreSQL pgBackRest 是最好的PG备份工具 ? (深入一些疑难问题 2)
    每天感悟突然想愤怒的时候,或别人认为你应该愤怒的时候,你不在愤怒,而是能理智的或冰冷的分析出为什么,原因是什么,并且尝试把自己放到他的位置去看明白原理或根本,恭喜你又升级了上次在安装和简单的实现了备份后,产生了很多的问题,基于这些问题我们持续的开始针对pgbackrest进行研究和发现......