泽恩小站-教程区 Help

drf初识

学习 drf 需要以 Django 的基础知识作为支撑,因此下面关于 Django 基础部分就不会展开讲解了。如果你感觉下面的代码理解起来非常困难,磨刀不误砍柴工,那么建议先阅读我的 Django 基础教程:

drf 开发预备

首先在命令行创建博客文章的 App:

(venv) > python manage.py startapp article

创建一个简单的博客文章模型:

# article/models.py from django.db import models from django.utils import timezone # 博客文章 model class Article(models.Model): # 标题 title = models.CharField(max_length=100) # 正文 body = models.TextField() # 创建时间 created = models.DateTimeField(default=timezone.now) # 更新时间 updated = models.DateTimeField(auto_now=True) def __str__(self): return self.title

前后端分离中涉及到一个重要的概念: 序列化 (后面讲解)。Django 有一个非常优秀的库 djangorestframework(后称 DRF )。它可以帮我们封装好序列化的底层实现,让开发者专注于业务本身。

安装 DRF 及其他依赖库:

pip install djangorestframework==3.12.2 pip install markdown==3.3.3 pip install django-filter==2.4.0

然后将 App 注册列表:

# drf_vue_blog/settings.py INSTALLED_APPS = [ ... 'rest_framework', 'article', ]

接着还需要添加 DRF 的登录视图,以便 DRF 自动为你的可视化接口页面生成一个用户登录的入口:

# drf_vue_blog/urls.py ... from django.urls import include urlpatterns = [ ... path('api-auth/', include('rest_framework.urls')), ]

最后记得数据迁移:

(venv) > python manage.py makemigrations (venv) > python manage.py migrate

准备工作就做好了。

序列化与Django

前后端分离的核心思想之一,就是两端交互不通过模板语言,而只传输需要的数据。因此问题就来了。

在 Django 程序的运行过程中,变量都是存储在服务器的内存中;更要命的是,后端 Django 程序中存储的是 Python 变量,而前端的浏览器中是 Javascript 变量,这两者是无法直接通过你家的网线进行传递和交流的。因此需要规定一个“标准格式”,前后端都根据这个标准格式,对资源进行保存、读取、传输等操作。

JSON 就是这种标准格式之一。它很轻量,表示出来就是个字符串,可以直接被几乎所有的语言读取,非常方便。

举个例子,把 Python 对象转换为 JSON ,这被称为序列化 (serialization):

>>> import json >>> person = dict(name='Trump', age=82) >>> json.dumps(person) # 这是个字符串 '{"age": 82, "name": "Trump"}'

把 JSON 转换为 Javascript 对象,被称为反序列化

>>> json_str = '{"age": 82, "name": "Trump"}' >>> json.loads(json_str) # 这是个 js 对象 {'age': 82, 'name': 'Trump'}

总之,把变量从内存中变成可存储或传输的过程称之为序列化 ,反过来把变量内容从序列化的对象重新读到内存里称之为反序列化

回顾 Django 传统流程对一个网络请求的处理:

def a_list(request): articles = Article.objects.all() return render(..., context={'articles': articles})

视图函数将数据作为上下文返回,通过模板引擎将上下文渲染为页面中的数据。

Restful 的处理流程仅增加了一步,即对数据序列化的处理:

def a_list(request): articles = Article.objects.all() # 序列化数据 serializer = Serializer(articles, many=True) return JsonResponse(serializer.data, safe=False)

数据被序列化为 Json 字符串,直接交由前端处理。

这就是前后端分离的雏形:

  • 后端提供数据;

  • 前端专注于操作数据、渲染页面。

Hello World

按照这个思路,我们来写一个文章列表接口吧。

article 模型在前面已经写好了,接下来写视图:

# article/views.py from django.http import JsonResponse from article.models import Article # 这个 ArticleListSerializer 暂时还没有 from article.serializers import ArticleListSerializer def article_list(request): articles = Article.objects.all() serializer = ArticleListSerializer(articles, many=True) return JsonResponse(serializer.data, safe=False)

代码一共就 3 行:

  • 取出所有文章的 QuerySet

  • 根据 QuerySet 数据,创建一个序列化器;

  • 将序列化后的数据以 Json 的形式返回。

跟说好的一样,返回的东西不再是传统的模板了,而是 Json 数据。

代码里的序列化器 ArticleListSerializer 我们还没写,接下来就完成它。

新建一个 article/serializers.py 的文件,写入下面的代码:

# article/serializers.py from rest_framework import serializers class ArticleListSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) title = serializers.CharField(allow_blank=True, max_length=100) body = serializers.CharField(allow_blank=True) created = serializers.DateTimeField() updated = serializers.DateTimeField()

序列化类看起来与 Django 的 Form 表单类非常的类似。它指定了接口数据中各个字段的具体类型,自动对请求响应中的数据进行序列化和反序列化的转换。其底层实现逻辑已经由 DRF 框架封装好了,在入门阶段通常不需要你操心。

最后将各级 urls.py 配置好:

# drf_vue_blog/urls.py ... urlpatterns = [ ... path('api/article/', include('article.urls', namespace='article')), ]

以及:

# article/urls.py from django.urls import path from article import views app_name = 'article' urlpatterns = [ path('', views.article_list, name='list'), ]

代码部分就完成了。

接下来创建一个管理员用户,并在后台中随意给 article 添加几个测试数据,启动服务器并在浏览器中访问 http://127.0.0.1:8000/api/article/ ,可以看到页面中返回的 Json 字符串如下(稍作了排版):

[ { "body": "Maybe say somthing here...", "created": "2020-06-15T09:24:18Z", "id": 1, "title": "My first post", "updated": "2020-06-15T09:24:38.622789Z" }, { "body": "Second test..", "created": "2020-06-15T09:24:38Z", "id": 2, "title": "Another post", "updated": "2020-06-15T09:24:58.253400Z" }, { "body": "Some content also..", "created": "2020-06-15T09:24:58Z", "id": 3, "title": "Third article with awesome things", "updated": "2020-06-15T09:25:25.602840Z" } ]

虽然简陋,但是你已经成功完成了一个简单的接口。

Last modified: 06 January 2025