Flutter&Python项目实战: 从0到1实现背单词App(3) 单词本的上传和下载接口

123 阅读4分钟

不要追求更好的方法来尽快完成任务,而要追求更好的任务,让你做得不想停下来。

在进行后端接口开发中, 一般遵循一下顺序:

  1. 需求整理和数据库设计
  2. 编写model和view代码(view是存放业务代码的地方).
  3. 配置路由.
  4. 测试.

1. 需求整理

  • 前端通过分页的方式来获取单词本列表. 每个数据项应该包含基本信息和下载地址.
  • 前端通过下载地址下载指定图书.
  • 管理员通过管理后台上传单词本.

2. 数据层

新建api.models.book.py文件, 构建单词本的实体类Book:

from django.db import models


class Book(models.Model):
    name = models.CharField('书名', max_length=100)
    path = models.FileField('上传文件', upload_to='book/') # 上传到 settings.MEDIA_ROOT + upload_to 文件夹内

    class Meta:
        ordering = ('pk', ) # 排序方式按主键升序

这里建议大家打开django的文档认真阅读这些新字段的具体使用.

api.models.book.py创建model的序列化和反序列化处理类, 它有几个作用:

  • 序列化model为json传递给前端.
  • 验证前端的请求参数并反序列化前端的入参为python对象.
from rest_framework import serializers

class BookSerializer(serializers.ModelSerializer):
    path = serializers.FileField(use_url=False) # use_url=False会将绝对路径URL转换为相对路径

    class Meta:
        model = Book # 关联指定的 model
        fields = '__all__' # model 所有字段都需要处理

3. view 层

这里我们处理两个业务: 拉取单词本列表和处理下载单词本请求.

3.1 统一处理返回json格式

作者在做前端时, 被后端各种不规范的接口返回搞得头大, 现在让我们一起处理一下. 大部分语言的架构都是基于继承进行代码组织的, 在这里我们通过override基类的方法, 来统一后端的返回格式:

{
    "message": xxx,
    "code": xxx,
    "data": xxx
}

新建api.views.base.py文件, 拦截返回数据并组织成统一的格式:

from rest_framework.views import APIView


class BaseView(APIView):
    def finalize_response(self, request, response, *args, **kwargs):
        response.data = {
                'code': 0,
                'message': 'ok',
                'data': response.data
            }   
        return super(BaseView, self).finalize_response(request, response, *args, **kwargs)

这里假设所有response都是成功状态, 请大家思考如何处理异常状态, 可以加群和作者讨论.

3.1 单词本分页接口

新建api.views.book.py文件, 处理拉取单词本的业务:

from rest_framework import viewsets, mixins
from .base import BaseView
from api.models.book import BookSerializer, Book


class BookViewSet(BaseView, mixins.ListModelMixin, viewsets.GenericViewSet): # 这里只需要处理分页
    serializer_class = BookSerializer # 序列化和反序列化
    queryset = Book.objects.all() # 类似数据库连接
    authentication_classes = [] # 不需要用户认真
    permission_classes = [] # 不需要鉴权

嘿, 就这么简单

4. 配置路由

前端的http请求到达后端程序时需要通过路由转发到对应的处理函数/类中, 那么这个路由规则需要我们来配置一下:

# api.urls.py
from django.urls import path, include
from rest_framework.routers import SimpleRouter
from api.views.book import BookViewSet

app_name = 'api'

router = SimpleRouter()
router.register('book', BookViewSet, basename='book') # 自动处理路径+请求方法 -> 处理类/函数之间的映射关系

urlpatterns = [
    path('', include(router.urls)),
]

# backend.urls.py
from django.urls import path, include

urlpatterns = [
    path('api/v1/', include('api.urls')), # api/v1/book 的请求转发给BookViewSet处理
    ...
]

5. 图书下载接口

有几个关键点:

  1. 通过前端的参数读取指定路径的文件.
  2. 返回csv格式文件.

到这里大家应该知道下一步是什么了, 是的, 我们先编写view层代码:

# api.view.download.py
from rest_framework import response, renderers, views
from django.conf import settings
from os.path import join


class CSVRenderer(renderers.BaseRenderer): # 默认是JsonRender, 但是现在我们需要定制一下
    media_type = 'text/csv'
    format = 'csv'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return data


class DownloadView(views.APIView): # 注意这里没继承BaseView
    authentication_classes = []
    permission_classes = []
    renderer_classes = [CSVRenderer] # 将response渲染成csv文件格式

    def get(self, request, path):
        path = join(settings.MEDIA_ROOT, path) # 根据前端传来的path参数, 获取文件本地路径
        data = open(path, 'rb').read() # 读取二进制
        return response.Response(data=data)

然后呢? 当然是配置路由喽:

# backend.urls.py
from django.urls import re_path
from api.views.download import DownloadView

urlpatterns = [
    ...
    re_path(r'^upload/(?P<path>.*)$', DownloadView.as_view()), # 子匹配的值会作为参数传入处理函数中
    ...
]

6. 使用django-admin进行图书管理

Django 自带后台管理功能, 我们需要做的只是将需要管理的model注册一下:

# api.admin.py

from django.contrib import admin
from api.models.book import Book

admin.site.register(Book)

7. 迁移, 运行, 测试

刚才我们只是配置了model层, 但是还没有真正去创建数据库表结构, 所以在运行之前还要进行数据库迁移. 迁移和运行的方式请参考上一章. 运行之后我们需要对接口进行测试, 作者使用的是Postman工具, 大家可以选择自己熟悉的工具进行测试. 最后, 大家打开127.0.0.1:8000/admin, 进入管理页, 上传单词本吧(注意必须是csv格式的哦~).

csv格式的单词本大家可以去这里下载: github.com/ourongxing/…, 感谢开源~

很简单是不是. 但是后端能做的东西还是有很多的, 下面列举一些, 供读者以后自己练习:

  • 使用django-admin进行图书管理.
  • 加入用户管理模块.
  • 支持https.
  • 将服务端部署到云端等等...

代码已开源: github.com/oooooocean/…, 如果觉得有帮助, 请给个Star, 鼓励下作者.

如果大家对代码有疑问, 或者遇到什么问题, 欢迎加群和作者讨论: