Skip to content

Latest commit

 

History

History
252 lines (181 loc) · 7.93 KB

30-drf初识.md

File metadata and controls

252 lines (181 loc) · 7.93 KB

学习 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 字符串,直接交由前端处理。

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

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

这里又出现了与前后端分离联系很紧密的新概念:Rest(表现层状态转化) 和 Restful。Restful 架构是指客户端和服务器之间的交互、操作符合 Rest 规范,即:每一个URI代表一种资源;客户端和服务器之间,传递资源的表现层;客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。有点难理解,推荐读物阮一峰的博客知乎文章

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"
    }
]

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

创建管理员用户、在后台中添加数据是非常基础的内容,如果不清楚请参照 这篇文章

如果你进入后台发现页面没有样式,那是因为静态文件未配置路由引起的。解决这个问题请参考 配置静态文件