• 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 处理数据库方面的请求

    接口文档案例

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

    3、路由分发函数

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

    1. path('customers/', 'app.views.list_customer', method='get'),
    2. path('customers/', 'app.views.add_customer', method='post'),

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

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

     vi Django_demo/Django_demo/urls.py

    1. #添加路由分支,将api/mgr/ 转交给mgr应用下的子路由
    2. path('api/mgr/', include('mgr.urls')),

     vi Django_demo/Django_demo/settings.py

    1. INSTALLED_APPS = [
    2. 'simpleui',
    3. 'django.contrib.admin',
    4. 'django.contrib.auth',
    5. 'django.contrib.contenttypes',
    6. 'django.contrib.sessions',
    7. 'django.contrib.messages',
    8. 'django.contrib.staticfiles',
    9. 'paas',
    10. 'mgr', #添加
    11. ]

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

    定义api函数

    vi Django_demo/mgr/k8s.py

    1. import json
    2. from django.http import JsonResponse
    3. from django.shortcuts import render
    4. def dispatcher(request): # 将请求参数统一放入request 的 params 属性中,方便后续处理
    5. # 判断应用的请求模式为GET时,取出请求后续的内容
    6. if request.method == 'GET':
    7. request.params = request.GET
    8. # POST/PUT/DELETE 请求 参数 从 request 对象的 body 属性中获取
    9. elif request.method in ['POST','PUT','DELETE']:
    10. # 根据接口,POST/PUT/DELETE 请求的消息体都是 json格式
    11. request.params = json.loads(request.body)
    12. # 根据不同的action分派给不同的函数进行处理
    13. action = request.params['action']
    14. if action == 'list_customer':
    15. return listcustomers(request) #查看
    16. elif action == 'add_customer':
    17. return addcustomer(request) #新增
    18. elif action == 'modify_customer':
    19. return modifycustomer(request) #修改
    20. elif action == 'del_customer':
    21. return deletecustomer(request) #删除
    22. else:
    23. return JsonResponse({'ret': 1, 'msg': '不支持该类型http请求'})
    24. def listcustomers(request):
    25. return JsonResponse({'ret': 1, 'msg': '展现数据'})
    26. def addcustomer(request):
    27. return JsonResponse({'ret': 1, 'msg': '添加数据'})
    28. def modifycustomer(request):
    29. return JsonResponse({'ret': 1, 'msg': '修改数据'})
    30. def deletecustomer(request):
    31. return JsonResponse({'ret': 1, 'msg': '删除数据'})

     定义mgr下的子路由

    vi  Django_demo/mgr/urls.py

    1. from django.urls import path
    2. from .k8s import dispatcher
    3. urlpatterns = [
    4. path('customers/', dispatcher), #定义路由
    5. ]

    4、测试验证

    http://127.0.0.1:8000/api/mgr/customers/?action=list_customer

    二、列出数据

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

    1. {
    2. "ret": 0,
    3. "retlist": [
    4. {
    5. "ClusterName": "acp-r1-1",
    6. "id": 1,
    7. "NodeSum": "100",
    8. "PrometheusAddress": "192.168.1.1"
    9. },
    10. {
    11. "ClusterName": "123123",
    12. "id": 4,
    13. "NodeSum": "123123",
    14. "PrometheusAddress": "123123"
    15. }
    16. ]
    17. }

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

    1、添加数据模型

    vi Django_demo/mgr/models.py

    1. #直接拷贝之前paas的
    2. from django.db import models
    3. class PaasInfo(models.Model):
    4. # 集群名称
    5. ClusterName = models.CharField(max_length=200)
    6. # node主机数量
    7. NodeSum = models.CharField(max_length=200)
    8. # prometheus地址
    9. PrometheusAddress = models.CharField(max_length=200)

    2、修改列出数据函数

    vi Django_demo/mgr/k8s.py

    1. #先导入之前paas使用的模型,也就是链接paas用的数据库
    2. from paas.models import PaasInfo
    3. def listcustomers(request):
    4. # 返回一个 QuerySet 对象 ,包含所有的表记录
    5. qs = PaasInfo.objects.values()
    6. # 将 QuerySet 对象 转化为 list 类型
    7. # 否则不能 被 转化为 JSON 字符串
    8. retlist = list(qs)
    9. return JsonResponse({'ret': 0, 'retlist': retlist})

    3、访问测试

    1. import requests,pprint
    2. response = requests.get('http://127.0.0.1:8000/api/mgr/customers/?action=list_customer')
    3. pprint.pprint(response.json())

     返回

    1. {
    2. "ret": 0,
    3. "retlist": [
    4. {
    5. "ClusterName": "acp-r1-1",
    6. "NodeSum": "100",
    7. "PrometheusAddress": "192.168.1.1",
    8. "id": 1
    9. },
    10. {
    11. "ClusterName": "123123",
    12. "NodeSum": "123123",
    13. "PrometheusAddress": "123123",
    14. "id": 2
    15. }
    16. ]
    17. }

    三、添加数据

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

    1. {
    2. "action":"add_customer",
    3. "data":{
    4. "ClusterName":"X4-scp-1-1",
    5. "NodeSum":"222",
    6. "PrometheusAddress":"192.168.1.2"
    7. }
    8. }

    1、修改添加函数

    vi Django_demo/mgr/k8s.py

    1. def addcustomer(request):
    2. info = request.params['data']
    3. # 从请求消息中 获取要添加客户的信息
    4. # 并且插入到数据库中
    5. # 返回值 就是对应插入记录的对象
    6. record = PaasInfo.objects.create(ClusterName=info['ClusterName'] ,
    7. NodeSum=info['NodeSum'] ,
    8. address=info['PrometheusAddress'])
    9. return JsonResponse({'ret': 0, 'id':record.id})

    2、关闭 Csrf

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

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

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

    vi Django_demo/Django_demo/settings.py

    1. MIDDLEWARE = [
    2. 'django.middleware.security.SecurityMiddleware',
    3. 'django.contrib.sessions.middleware.SessionMiddleware',
    4. 'django.middleware.common.CommonMiddleware',
    5. #将下面这行注释掉
    6. # 'django.middleware.csrf.CsrfViewMiddleware',
    7. 'django.contrib.auth.middleware.AuthenticationMiddleware',
    8. 'django.contrib.messages.middleware.MessageMiddleware',
    9. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    10. ]

    3、测试

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

    vi main.py

    1. import requests,pprint
    2. # 构建添加 客户信息的 消息体,是json格式
    3. payload = {
    4. "action":"add_customer",
    5. "data":{
    6. "ClusterName":"abc",
    7. "NodeSum":"133",
    8. "PrometheusAddress":"192.168.1.2"
    9. }
    10. }
    11. # 发送请求给web服务
    12. response = requests.post('http://127.0.0.1:8000/api/mgr/customers/',json=payload)
    13. pprint.pprint(response.json())

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

    http://127.0.0.1:8000/api/mgr/customers?action=list_customer

    四、修改数据

    1、请求格式

    1. {
    2. "action":"modify_customer",
    3. "id": 3,
    4. "newdata":{
    5. "ClusterName":"gfs-r3-1",
    6. "NodeSum":"5000",
    7. "PrometheusAddress":"192.168.1.21"
    8. }
    9. }

    2、添加修改函数

    1. def modifycustomer(request):
    2. # 从请求消息中 获取修改客户的信息
    3. # 找到该客户,并且进行修改操作
    4. customerid = request.params['id']
    5. newdata = request.params['newdata']
    6. print(customerid,newdata)
    7. try:
    8. # 根据 id 从数据库中找到相应的客户记录
    9. customer = PaasInfo.objects.get(id=customerid)
    10. except PaasInfo.DoesNotExist:
    11. return {
    12. 'ret': 1,
    13. 'msg': f'id 为`{customerid}`的客户不存在'
    14. }
    15. #注意修改每个判断的3个变量
    16. if 'ClusterName' in newdata:
    17. customer.ClusterName = newdata['ClusterName']
    18. if 'NodeSum' in newdata:
    19. customer.NodeSum = newdata['NodeSum']
    20. if 'PrometheusAddress' in newdata:
    21. customer.PrometheusAddress = newdata['PrometheusAddress']
    22. # 注意,一定要执行save才能将修改信息保存到数据库
    23. customer.save()
    24. return JsonResponse({'ret': 0})

    3、测试

    vi main.py

    1. import requests,pprint
    2. # 构建添加 客户信息的 消息体,是json格式
    3. payload = {
    4. "action":"modify_customer",
    5. "id": 3,
    6. "newdata":{
    7. "ClusterName":"gfs-r3-1",
    8. "NodeSum":"5000",
    9. "PrometheusAddress":"192.168.1.21"
    10. }
    11. }
    12. # 发送请求给web服务
    13. response = requests.post('http://127.0.0.1:8000/api/mgr/customers/',json=payload)
    14. pprint.pprint(response.json())

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

    五、删除数据

    1、数据格式

    1. {
    2. "action":"del_customer",
    3. "id": 6
    4. }

     2、添加删除函数

    1. def deletecustomer(request):
    2. customerid = request.params['id']
    3. try:
    4. # 根据 id 从数据库中找到相应的客户记录
    5. customer = PaasInfo.objects.get(id=customerid)
    6. except PaasInfo.DoesNotExist:
    7. return {
    8. 'ret': 1,
    9. 'msg': f'id 为`{customerid}`的客户不存在'
    10. }
    11. # delete 方法就将该记录从数据库中删除了
    12. customer.delete()
    13. return JsonResponse({'ret': 0})

    3、测试

    vi main.py

    1. import requests,pprint
    2. # 构建添加 客户信息的 消息体,是json格式
    3. payload = {
    4. "action":"del_customer",
    5. "id": 4
    6. }
    7. # 发送请求给web服务
    8. response = requests.post('http://127.0.0.1:8000/api/mgr/customers/',json=payload)
    9. 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

    1. from django.http import JsonResponse
    2. from django.contrib.auth import authenticate, login, logout
    3. # 登录处理
    4. def signin( request):
    5. # 从 HTTP POST 请求中获取用户名、密码参数
    6. userName = request.POST.get('username')
    7. passWord = request.POST.get('password')
    8. # 使用 Django auth 库里面的 方法校验用户名、密码
    9. user = authenticate(username=userName, password=passWord)
    10. # 如果能找到用户,并且密码正确
    11. if user is not None:
    12. if user.is_active:
    13. if user.is_superuser:
    14. login(request, user)
    15. # 在session中存入用户类型
    16. request.session['usertype'] = 'mgr'
    17. return JsonResponse({'ret': 0})
    18. else:
    19. return JsonResponse({'ret': 1, 'msg': '请使用管理员账户登录'})
    20. else:
    21. return JsonResponse({'ret': 0, 'msg': '用户已经被禁用'})
    22. # 否则就是用户名、密码有误
    23. else:
    24. return JsonResponse({'ret': 1, 'msg': '用户名或者密码错误'})
    25. # 登出处理
    26. def signout( request):
    27. # 使用登出方法
    28. logout(request)
    29. return JsonResponse({'ret': 0})

     2、添加路由

    vi Django_demo/mgr/urls.py

    1. from django.urls import path
    2. from .k8s import dispatcher
    3. from .sign_in_out import signin,signout
    4. urlpatterns = [
    5. path('customers/', dispatcher),
    6. #添加登录、登出路由
    7. path('signin', signin),
    8. path('signout', signout),
    9. ]

    3、测试

    vi main.py

    1. import requests,pprint
    2. #这个账户密码是之前设置create直接拿来用
    3. payload = {
    4. 'username': 'root',
    5. 'password': '12345678'
    6. }
    7. response = requests.post('http://127.0.0.1:8000/api/mgr/signin',data=payload)
    8. pprint.pprint(response.json())

    返回

    1. #只有0是正确的,其他的非0都会返回msg的提升信息
    2. {'ret': 0}
  • 相关阅读:
    SpringBoot项目创建
    MySQL的分库分表
    shallow fusion--学习笔记
    汽车与交通运输行业智能车辆体验 | 达索系统百世慧®
    备库failover升级
    小米发布CyberOn仿生机器人;多伦多大学『3D和几何深度学习』课程资料;英伟达神经场工具库;商汤开源项目集锦;前沿论文 | ShowMeAI资讯日报
    【小程序】微信小程序自定义导航栏及其封装
    docker 的入门笔记
    Android XML文件结构 和 用XmlPullParser 来解析xml文件
    02【UML统一建模语言】
  • 原文地址:https://blog.csdn.net/qq_42883074/article/details/133908851