对资源的增查改删处理

前面已经说过,如果采用前后端分离的架构开发, 后端几乎不负责任何展现界面的工作,而是负责对数据进行管理 。

数据的管理,主要就是:响应前端的请求, 对数据资源的 增加、修改、删除、列出。

下面我们就以 BYSMS 系统中 客户信息 数据为例,看看如何进行 数据的增查改删 操作。

现在我们的系统,API接口 已经由架构师定义好了, 点击这里查看

其中包括了客户数据的 增查改删 接口,现在我们就根据这个接口文档,来实现后端。

添加处理请求模块 和 url 路由

首先我们应添 添加一个 模块文件, 专门处理 对客户 Customer 数据的 请求。

而且,这是针对 管理员 类型账号的 请求。

所以,我们可以在 mgr目录下新增一个文件 customer.py 。

从接口文档,我们可以发现对资源的增删改查 操作,涉及到使用不同的 请求类型 ,包括 POST/DELETE/PUT/GET。 而且请求的参数中都有action 参数表明这次请求的操作具体是什么。

Django的url路由不支持直接 根据 http请求的类型 和请求体里面的参数 进行路由。

所以我们为了能够把 不同的 API 请求分配给不同的函数进行处理,就需要自己编写一个请求分发函数, 根据 http请求的类型 和请求体里面的参数 分发(或者说路由)给 不同的函数进行处理。

我们可以 在 customer.py 中定义如下 dispatcher 函数

def dispatcher(request):
    # 将请求参数统一放入request 的 params 属性中,方便后续处理
    if request.method == 'GET':
        request.params = request.GET
        return  listcustomers(request)

    elif request.method in ['POST','PUT','DELETE']:
        request.params = json.loads(request.body)
        # 根据不同的action分派给不同的函数进行处理
        if request.params['action'] == 'add_customer':
            return addcustomer(request)
        if request.params['action'] == 'modify_customer':
            return modifycustomer(request)
        elif request.params['action'] == 'del_customer':
            return deletecustomer(request)

    else:
        return JsonResponse({'ret': 1, 'msg': '不支持该类型http请求'})

该函数 把 请求消息中的参数统一放入到 request请求对象的params 属性中。

params 属性 被 做成一个 dict 类型 , 方便后面的处理函数来获取消息中的参数。

然后 dispatch函数再根据 请求的 类型 和 action 参数的值 决定由那个函数具体处理该请求消息。

比如 action 参数 为 ‘add_customer’ 的 请求 就由 addcustomer 函数 进行处理。



接下来,根据 API 接口 ,我们发现 凡是 API 请求url为 /api/mgr/customers 的,都属于 客户 相关的API, 都应该交由 我们上面定义的dispatch函数进行分派处理。

那么我们需要在Django的url路由文件中加入对应的路由。

前面我们已经在 总路由文件 bysms/urls.py 中定义了,如下部分


    # 凡是 url 以 api/mgr  开头的,
    # 都根据 mgr.urls 里面的 子路由表进行路由
    path('api/mgr/', include('mgr.urls')),

所以我们只需要在 mgr 目录下面的 urls.py 路由文件中 加入声明即可, 如下所示

from django.conf.urls import url
from mgr.sign_in_out import signin, signout

# 导入 dispatcher 函数
from mgr.customer import dispatcher

urlpatterns = [

    url('signin', signin),
    url('signout', signout),
    
    #url后缀部分为 customers 的,由 dispatcher函数处理
    url('customers', dispatcher),

]

这样,就表示 凡是 API 请求url为 /api/mgr/customers 的,都交由 我们上面定义的dispatch函数进行分派处理



列出客户

通常数据资源的 增查改删 里面的 查 就是 查看,对应的就是列出数据资源。

根据接口文档,列出客户数据接口,后端返回的数据格式如下

{
    "ret": 0,
    "retlist": [
        {
            "address": "江苏省常州武进市白云街44号",
            "id": 1,
            "name": "武进市 袁腾飞",
            "phonenumber": "13886666666"
        },
        
        {
            "address": "北京海淀区",
            "id": 4,
            "name": "北京海淀区代理 蔡国庆",
            "phonenumber": "13990123456"
        }
    ]              
}

看到没有,这里我们无需 将数据库中获取的数据 转化为 供浏览器展示的HTML。

在前后端分离的开发架构中,如何展示数据,那是前端的事情。

我们后端只需要根据接口文档, 返回原始数据就行。

我们可以使用如下的函数来返回数据库的所有的 客户数据信息

def listcustomers(request):
    # 返回一个 QuerySet 对象 ,包含所有的表记录
    qs = Customer.objects.values()

    # 将 QuerySet 对象 转化为 list 类型
    # 否则不能 被 转化为 JSON 字符串
    retlist = list(qs)

    return JsonResponse({'ret': 0, 'retlist': retlist})

可以发现,无需转化数据为HTML, 后端的代码任务也大大减轻。



添加客户

通常数据资源的 增查改删 里面的 增 就是 添加,对应的就是添加数据资源。

根据接口文档,添加客户数据接口,前端提供的客户数据格式如下

{
    "action":"add_customer",
    "data":{
        "name":"武汉市桥西医院",
        "phonenumber":"13345679934",
        "address":"武汉市桥西医院北路"
    }
}

我们可以使用如下的函数来处理

def addcustomer(request):

    info    = request.params['data']

    # 从请求消息中 获取要添加客户的信息
    # 并且插入到数据库中
    Customer.objects.create(name=info['name'] ,
                            phonenumber=info['phonenumber'] ,
                            address=info['address'])


    return JsonResponse({'ret': 0})

Customer.objects.create 方法就可以添加一条Customer表里面的记录。



修改客户信息

数据资源的 增查改删 里面的 就是 改动,对应的就是修改数据资源。

根据接口文档,修改客户数据接口,前端提供的数据格式如下

{
    "action":"modify_customer",
    "id": 6,
    "newdata":{
        "name":"武汉市桥北医院",
        "phonenumber":"13345678888",
        "address":"武汉市桥北医院北路"
    }
}

我们可以使用如下的函数来处理

def modifycustomer(request):

    # 从请求消息中 获取修改客户的信息
    # 找到该客户,并且进行修改操作
    
    customerid = request.params['id']
    newdata    = request.params['newdata']

    try:
        # 根据 id 从数据库中找到相应的客户记录
        customer = Customer.objects.get(id=customerid)
    except Customer.DoesNotExist:
        return  {
                'ret': 1,
                'msg': f'id 为`{customerid}`的客户不存在'
        }


    if 'name' in  newdata:
        customer.name = newdata['name']
    if 'phonenumber' in  newdata:
        customer.phonenumber = newdata['phonenumber']
    if 'address' in  newdata:
        customer.address = newdata['address']

    # 注意,一定要执行save才能将修改信息保存到数据库
    customer.save()

    return JsonResponse({'ret': 0})



删除客户

数据资源的 增查改删 里面的 就是 删除,对应的就是删除数据资源。

根据接口文档,删除客户数据接口,前端只需要提供要删除的客户的ID。

数据格式如下

{
    "action":"del_customer",
    "id": 6
}

我们可以使用如下的函数来处理

def deletecustomer(request):

    customerid = request.params['id']

    try:
        # 根据 id 从数据库中找到相应的客户记录
        customer = Customer.objects.get(id=customerid)
    except Customer.DoesNotExist:
        return  {
                'ret': 1,
                'msg': f'id 为`{customerid}`的客户不存在'
        }

    # delete 方法就将该记录从数据库中删除了
    customer.delete()

    return JsonResponse({'ret': 0})



后端对 客户数据的增查改删已经实现了,那么怎么测试呢?

同样,可以使用 requests库构造API请求,发送给服务端进行测试。

大家可以根据前面的例子,自己编写测试程序。



和前端集成

最终我们的产品 前端和后端系统会集成在一起成为一个完整的系统。

部署到生产环境(生产环境就是正式的线上运营环境)运行的架构往往比较复杂。我们在后面有专门的章节讲述 一个比较完整的线上环境 如何搭建。

这里我们讲述开发环境下, 前后端分离的架构如何简单集成。



前端环境其实就是 一些前端的代码和资源文件,包括 js文件、html文件、css文件 还有 图片视频文件等。

我们模拟前端团队开发的 前端 系统 打包在这里 ,点击这里下载

下载好以后,可以解压该 z_dist.zip 文件到项目根目录下面,形成一个目录 z_dist。

该目录下面就是前端的 代码资源文件。

Django的开发环境也可以从浏览器访问这些前端的资源文件。

但是前端文件都是静态文件,需要我们配置一下Django的配置文件, 到哪里寻找除了API请求之外的其他文件访问。

请打开 bysms/urls.py 文件, 修改内容如下

from django.contrib import admin

# 导入一个include函数
from django.urls import path, include

# 静态文件服务
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),

    # 凡是 url 以 agent/  开头的,
    # 都根据 agent.urls 里面的 子路由表进行路由
    path('agent/', include('agent.urls')),

    # 凡是 url 以 api/mgr  开头的,
    # 都根据 mgr.urls 里面的 子路由表进行路由
    path('api/mgr/', include('mgr.urls')),

]  +  static("/", document_root="./z_dist")

最后的

+  static("/", document_root="./z_dist")

就是在url 路由中加入 前端静态文件的查找路径。

这样如果 http请求的url 不是以 admin/ agent/ api/mgr 开头, Django 就会认为是要访问 z_dist目录下面的静态文件。

好了,现在我们 运行如下命令,启动Django 开发服务器

python manage.py runserver 80

然后我们打开浏览器,输入如下网址:

http://localhost/mgr/sign.html

就会出现 前端开发的 登录界面,如下

image



输入正确的用户名、密码登录后,进入管理员操作界面,如下

image

这是前端开发的 客户管理界面,可以在界面上进行客户的 增查改删操作, 这些操作会触发API 请求发送给我们的后端服务。

大家可以操作一下看看, 后端是否能够正确的响应。



目前为止,我们系统的完整代码,点击这里下载



上一页 下一页