Python 框架学习 Django篇 (四) 数据库增删改查(CURD)

在上一章结尾我们了解到如采用前后端开发分离的架构模式开发,后端几乎不负责任何展现界面的工作,只负责对数据进行管理 ,对数据的管理主要体现在: (增加、修改、删除、列出 具体的接口参考大佬的文档BYSMS系统 API 接口 1.0 | 白月黑羽 本章只做练习

一、添加应用、路由分发、api规划

接口文档明确说明了这是针对管理员用户的请求,我们在前面创建过一个paas的应用专门处理paas相关的请求,所以我们可以再为管理员用户专门创建一个应用mgr来处理相关的 请求

1、创建 mgr应用目录

复制代码
python manage.py startapp mgr 

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

前面我们都是直接把函数写到应用的views.py文件里面来处理http请求的,后续如果我们需要添加的函数数量非常多就不方便了,我们可以定义多个函数文件来处理这种请求,比如定义cluster.py 来处理集群相关的请求,sql.py 处理数据库方面的请求

接口文档案例

python 复制代码
GET  /api/mgr/customers?action=list_customer  HTTP/1.1

#请求参数
http 请求消息 url 中 需要携带如下参数是action 填写的值为list_customer
通过接口文档可以看到对资源的增删改查操作都是同一个URL(/api/mgr/customers)
而不同的请求操作,使用了不同的方法 GET  POST PUT DELETE  

3、路由分发函数

Django 的 url路由功能 不支持 根据 HTTP 请求的方法 和请求体里面的参数 进行路由,如下

复制代码
path('customers/', 'app.views.list_customer', method='get'),
path('customers/', 'app.views.add_customer',  method='post'),

碰到这种情况,我们可以编写一个函数去将所有请求做条件判断,转发给不同的函数处理

按照接口文档的url,我们需要将/api/mgr/开头的请求都交给mgr的应用路由处理

vi Django_demo/Django_demo/urls.py

python 复制代码
#添加路由分支,将api/mgr/ 转交给mgr应用下的子路由
path('api/mgr/', include('mgr.urls')),

vi Django_demo/Django_demo/settings.py

python 复制代码
INSTALLED_APPS = [
    'simpleui',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'paas',

    'mgr',   #添加
]

我们添加了应用配置和路由方向了,下面我们应该去定义api所在的文件和具体的路由配置

定义api函数

vi Django_demo/mgr/k8s.py

python 复制代码
import json

from django.http import JsonResponse
from django.shortcuts import render

def dispatcher(request):  # 将请求参数统一放入request 的 params 属性中,方便后续处理


    # 判断应用的请求模式为GET时,取出请求后续的内容
    if request.method == 'GET':
        request.params = request.GET

    # POST/PUT/DELETE 请求 参数 从 request 对象的 body 属性中获取
    elif request.method in ['POST','PUT','DELETE']:
        # 根据接口,POST/PUT/DELETE 请求的消息体都是 json格式
        request.params = json.loads(request.body)


    # 根据不同的action分派给不同的函数进行处理
    action = request.params['action']
    if action == 'list_customer':
        return listcustomers(request)      #查看
    elif action == 'add_customer':
        return addcustomer(request)        #新增
    elif action == 'modify_customer':
        return modifycustomer(request)     #修改
    elif action == 'del_customer':
        return deletecustomer(request)     #删除

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

def listcustomers(request):
    return JsonResponse({'ret': 1, 'msg': '展现数据'})
def addcustomer(request):
    return JsonResponse({'ret': 1, 'msg': '添加数据'})
def modifycustomer(request):
    return JsonResponse({'ret': 1, 'msg': '修改数据'})
def deletecustomer(request):
    return JsonResponse({'ret': 1, 'msg': '删除数据'})

定义mgr下的子路由

vi Django_demo/mgr/urls.py

python 复制代码
from django.urls import path

from .k8s import dispatcher
urlpatterns = [

    path('customers/', dispatcher),  #定义路由
]

4、测试验证

python 复制代码
http://127.0.0.1:8000/api/mgr/customers/?action=list_customer

二、列出数据

列出也就是查看,增删改查里面的查询,http 响应消息 body 中, 数据以json格式存储,下面是最开头的接口文档中常见的接口数据返回格式

python 复制代码
{
    "ret": 0,
    "retlist": [
        {
            "ClusterName": "acp-r1-1",
            "id": 1,
            "NodeSum": "100",
            "PrometheusAddress": "192.168.1.1"
        },
        
        {
            "ClusterName": "123123",
            "id": 4,
            "NodeSum": "123123",
            "PrometheusAddress": "123123"
        }
    ]              
}

从上面格式中看出我们无需将数据库中获取的数据 转化为 供浏览器展示的HTML,在前后端分离中需要展示页面是前端的事情,我们只需要把数据提交上去即可

1、添加数据模型

vi Django_demo/mgr/models.py

python 复制代码
#直接拷贝之前paas的
from django.db import models

class PaasInfo(models.Model):
    # 集群名称
    ClusterName = models.CharField(max_length=200)

    # node主机数量
    NodeSum = models.CharField(max_length=200)

    # prometheus地址
    PrometheusAddress = models.CharField(max_length=200)

2、修改列出数据函数

vi Django_demo/mgr/k8s.py

python 复制代码
#先导入之前paas使用的模型,也就是链接paas用的数据库
from paas.models import PaasInfo

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

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

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

3、访问测试

python 复制代码
import  requests,pprint

response = requests.get('http://127.0.0.1:8000/api/mgr/customers/?action=list_customer')

pprint.pprint(response.json())

返回

python 复制代码
{
  "ret": 0,
  "retlist": [
    {
      "ClusterName": "acp-r1-1",
      "NodeSum": "100",
      "PrometheusAddress": "192.168.1.1",
      "id": 1
    },
    {
      "ClusterName": "123123",
      "NodeSum": "123123",
      "PrometheusAddress": "123123",
      "id": 2
    }
  ]
}

三、添加数据

添加数据,也就是新增数据,传输数据格式如下

python 复制代码
{
    "action":"add_customer",
    "data":{
        "ClusterName":"X4-scp-1-1",
        "NodeSum":"222",
        "PrometheusAddress":"192.168.1.2"
    }
}

1、修改添加函数

vi Django_demo/mgr/k8s.py

python 复制代码
def addcustomer(request):
    info    = request.params['data']

    # 从请求消息中 获取要添加客户的信息
    # 并且插入到数据库中
    # 返回值 就是对应插入记录的对象
    record = PaasInfo.objects.create(ClusterName=info['ClusterName'] ,
                                     NodeSum=info['NodeSum'] ,
                                     address=info['PrometheusAddress'])

    return JsonResponse({'ret': 0, 'id':record.id})

2、关闭 Csrf

新创建的项目, Django 缺省会启用一个 CSRF (跨站请求伪造) 安全防护机制。

在这种情况下, 所有的Post、PUT 类型的 请求都必须在HTTP请求头中携带用于校验的数据

为了简单起见,我们先临时取消掉CSRF的 校验机制,等以后有需要再打开

vi Django_demo/Django_demo/settings.py

python 复制代码
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',

     #将下面这行注释掉
    # 'django.middleware.csrf.CsrfViewMiddleware',  

    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

3、测试

随便建一个新文件用于测试请求url

vi main.py

python 复制代码
import  requests,pprint

# 构建添加 客户信息的 消息体,是json格式
payload = {
    "action":"add_customer",
    "data":{
        "ClusterName":"abc",
        "NodeSum":"133",
        "PrometheusAddress":"192.168.1.2"
    }
}

# 发送请求给web服务
response = requests.post('http://127.0.0.1:8000/api/mgr/customers/',json=payload)
pprint.pprint(response.json())

上面执行完毕后,可以在python上直接get 或者直接浏览器访问下面地址即可,下面有运行了两次所以会有两条相同的数据

python 复制代码
http://127.0.0.1:8000/api/mgr/customers?action=list_customer

四、修改数据

1、请求格式

python 复制代码
{
    "action":"modify_customer",
    "id": 3,
    "newdata":{
        "ClusterName":"gfs-r3-1",
        "NodeSum":"5000",
        "PrometheusAddress":"192.168.1.21"
    }
}

2、添加修改函数

python 复制代码
def modifycustomer(request):

    # 从请求消息中 获取修改客户的信息
    # 找到该客户,并且进行修改操作

    customerid = request.params['id']
    newdata    = request.params['newdata']
    print(customerid,newdata)

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

    #注意修改每个判断的3个变量
    if 'ClusterName' in  newdata:
        customer.ClusterName = newdata['ClusterName']
    if 'NodeSum' in  newdata:
        customer.NodeSum = newdata['NodeSum']
    if 'PrometheusAddress' in  newdata:
        customer.PrometheusAddress = newdata['PrometheusAddress']

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

    customer.save()

    return JsonResponse({'ret': 0})

3、测试

vi main.py

python 复制代码
import  requests,pprint

# 构建添加 客户信息的 消息体,是json格式
payload = {
    "action":"modify_customer",
    "id": 3,
    "newdata":{
        "ClusterName":"gfs-r3-1",
        "NodeSum":"5000",
        "PrometheusAddress":"192.168.1.21"
    }
}

# 发送请求给web服务
response = requests.post('http://127.0.0.1:8000/api/mgr/customers/',json=payload)
pprint.pprint(response.json())

忘截图了,上面是把id为3的值进行了修改

五、删除数据

1、数据格式

python 复制代码
{
    "action":"del_customer",
    "id": 6
}

2、添加删除函数

python 复制代码
def deletecustomer(request):
    customerid = request.params['id']

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

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

    return JsonResponse({'ret': 0})

3、测试

vi main.py

python 复制代码
import  requests,pprint

# 构建添加 客户信息的 消息体,是json格式
payload = {
    "action":"del_customer",
    "id": 4
}

# 发送请求给web服务
response = requests.post('http://127.0.0.1:8000/api/mgr/customers/',json=payload)
pprint.pprint(response.json())

六、简单实现登录逻辑

我们来实现一下登录功能,首先我们先在mgr目录下新建一个sign_in_out.py 这个文件后续就是来处理我们应用登录登出的api

首先我们思考一下怎么实现登录,无非就是将用户名和密码发送给后端,然后和数据库中数据进行对比后返回结果,在Django中有个内置的app 名为django.contrib.auth 默认包含在项目installed app中,这个app的model模型定义了一张名为auth_user的表,在我们第一次执行migrate 创建数据表时会跟随一块创建出来

django.contrib.auth 这个app已经自带了登录验证的功能,我们只需要调用一下即可

1、处理用户登录、登出请求

直接调用django.contrib.auth应用下的方法 authenticate 存储, login, logout

vi Django_demo/mgr/sign_in_out.py

python 复制代码
from django.http import JsonResponse

from django.contrib.auth import authenticate, login, logout

# 登录处理
def signin( request):
    # 从 HTTP POST 请求中获取用户名、密码参数
    userName = request.POST.get('username')
    passWord = request.POST.get('password')

    # 使用 Django auth 库里面的 方法校验用户名、密码
    user = authenticate(username=userName, password=passWord)
    
    # 如果能找到用户,并且密码正确
    if user is not None:
        if user.is_active:
            if user.is_superuser:
                login(request, user)
                # 在session中存入用户类型
                request.session['usertype'] = 'mgr'

                return JsonResponse({'ret': 0})
            else:
                return JsonResponse({'ret': 1, 'msg': '请使用管理员账户登录'})
        else:
            return JsonResponse({'ret': 0, 'msg': '用户已经被禁用'})
        
    # 否则就是用户名、密码有误
    else:
        return JsonResponse({'ret': 1, 'msg': '用户名或者密码错误'})


# 登出处理
def signout( request):
    # 使用登出方法
    logout(request)
    return JsonResponse({'ret': 0})

2、添加路由

vi Django_demo/mgr/urls.py

python 复制代码
from django.urls import path

from .k8s import dispatcher
from .sign_in_out import signin,signout
urlpatterns = [
    path('customers/', dispatcher),


    #添加登录、登出路由
    path('signin', signin),
    path('signout', signout),
]

3、测试

vi main.py

python 复制代码
import  requests,pprint

#这个账户密码是之前设置create直接拿来用
payload = {
    'username': 'root',
    'password': '12345678'
}

response = requests.post('http://127.0.0.1:8000/api/mgr/signin',data=payload)

pprint.pprint(response.json())

返回

python 复制代码
#只有0是正确的,其他的非0都会返回msg的提升信息
{'ret': 0}
相关推荐
小兔崽子去哪了5 分钟前
RFM 模型 项目实战
python
昨天那个谁谁16 分钟前
ROS2运行时报无法加载create_key等符号错误
c++·python·ros2
nju_spy1 小时前
python 算法题基础常用总结(比赛 or 机试 or 面试)
python·记忆化搜索·位运算·二分查找 - bisect·排序与lambda·最短路和最小生成树·堆与优先队列
Deng8723473481 小时前
自动化极验3点选验证码的识别与验证方案
运维·python·自动化
川石课堂软件测试1 小时前
自动化测试的基本概念及常用框架
数据库·python·功能测试·测试工具·单元测试·自动化·流程图
灰勒塔德1 小时前
jetson orin nano super开发指南
linux·服务器·python
8278209371 小时前
python scp 备份
开发语言·python
poggioxay2 小时前
JAVA零基础入门知识3(持续更新中)
java·开发语言·python
serve the people2 小时前
TensorFlow 基础训练循环(简化版 + 补全代码)
人工智能·python·tensorflow
木里先森2 小时前
解决报错:/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32‘ not found
linux·python