当前位置: 首页 > news >正文

Gerapy二次开发:用户管理专栏主页面开发

用户管理专栏主页面开发

  • 写在前面
  • 用户权限控制
  • 用户列表接口设计
  • 主页面开发
    • 前端
      • account/Index.vue
      • langs/zh.js
      • store.js
    • 后端
      • Paginator
        • 概述
        • 基本用法
        • 代码示例
        • 属性与方法
      • urls.py
      • views.py
    • 运行效果
  • 总结

欢迎加入Gerapy二次开发教程专栏!
本专栏专为新手开发者精心策划了一系列内容,旨在引领你深入探索Gerapy框架的二次迭代之旅。
本专栏将全面剖析Gerapy与Vue的源码架构,让你从内部了解它们的运作机制。
我们将分享实用的技巧,教你如何有效修复Gerapy中的异常问题,如何在现有基础上添加多样化的功能,以及如何对已有功能进行重构优化。

写在前面

读完本篇博客你可以学习到的知识:

  • 如何进行用户权限控制
  • 如何设计列表页(翻页)接口
  • 加深前后端开发经验,利用Django Paginator实现翻页请求

用户权限控制

一般情况下,超级管理员只会有一两个,我们想在前端知道登录用户的身份的话,必须要后端提供对应标识,但是现在已知的接口和缓存都没有存储用户身份标识,那么就需要我们重新开发提供了。

再来看下auth_user表,is_superuser就是用来标识超级管理员身份

在这里插入图片描述

这里就有两个方案了:

  1. 单独开一个接口获取当前登录用户身份
  2. 由于刚好是操作auth_user表用到,可以在拿auth_user表数据时顺便计算返回

这里看大家自己的选择,下面我用的是第二个方案,也就是每次请求列表页时,会返回is_superuser字段标识用户身份。

用户列表接口设计

  • 接口:/api/account/list?pageSize=10&currentPage=1
  • 请求:GET
  • 页数参数:pageSize,页码参数:currentPage
  • 响应接口字段:在这里插入图片描述

主页面开发

这是后续我们需要用到的四个文件的作用,Status.vue不需要用到,删除即可

在这里插入图片描述

前端

account/Index.vue

下面是全部代码,有些注释,具体的大家得自己熟悉熟悉,没法仔细讲,不过流程是清晰的。

<template><div class="panel"><panel-title :title="$lang.objects.accounts"><!--新增按钮实现--><router-link :to="{ name: 'accountCreate' }" tag="span"><el-button size="mini" type="success"><i class="fa fa-plus"></i>{{ $lang.buttons.create }}</el-button></router-link></panel-title><div class="panel-body"><!--遍历accounts--><el-tablev-loading="loading":data="accounts":element-loading-text="$lang.messages.loading":empty-text="$lang.messages.noData":style="{ width: '100%;' }"><!--各字段呈现实现--><el-table-column:label="$lang.columns.username"align="center"prop="username"min-width="30%"></el-table-column><el-table-column:label="$lang.columns.email"align="center"prop="email"min-width="30%"></el-table-column><el-table-column :label="$lang.columns.is_superuser" align="center" min-width="30%"><template slot-scope="props"><span v-if="props.row.is_superuser"><el-button icon="el-icon-check" round size="mini" type="primary"></el-button></span><span v-else><el-button icon="el-icon-close" round size="mini" type="primary"></el-button></span></template></el-table-column><el-table-column :label="$lang.columns.is_staff" align="center" min-width="30%"><template slot-scope="props"><span v-if="props.row.is_staff"><el-button icon="el-icon-check" round size="mini" type="primary"></el-button></span><span v-else><el-button icon="el-icon-close" round size="mini" type="primary"></el-button></span></template></el-table-column><el-table-column :label="$lang.columns.is_active" align="center" min-width="30%"><template slot-scope="props"><span v-if="props.row.is_active"><el-button icon="el-icon-check" round size="mini" type="primary"></el-button></span><span v-else><el-button icon="el-icon-close" round size="mini" type="primary"></el-button></span></template></el-table-column><el-table-column:label="$lang.columns.date_joined"align="center"prop="date_joined"min-width="30%"></el-table-column><el-table-column:label="$lang.columns.last_login"align="center"prop="last_login"min-width="30%"></el-table-column><!--isSupperUserLogin标识超级管理员身份--><el-table-column v-if="isSupperUserLogin" :label="$lang.columns.operations" align="center" min-width="50%"><template slot-scope="props"><router-link :to="{ name: 'accountEdit', params: { id: props.row.id } }" tag="span"><!--指定列跳转编辑页--><el-button size="mini" type="info"><i class="fa fa-edit"></i>{{ $lang.buttons.edit }}</el-button></router-link><!--指定列删除--><el-button size="mini" type="danger" @click="onSingleDelete(props.row.id)"><i class="fa fa-remove"></i>{{ $lang.buttons.delete }}</el-button></template></el-table-column></el-table></div></div>
</template>
<script type="text/javascript">
import PanelTitle from "../../components/PanelTitle";export default {data() {return {accounts: [],  // 用户数据列表loading: true,  // 加载中isSupperUserLogin: true,  // 是否是超级管理员身份totalCount: 0,  // 用户数据总数currentPage: 1,  // 当前页码pageSize: 10,  // 页数};},components: {PanelTitle,},created() {// 页面创建时请求数据this.getAccountData(this.currentPage, this.pageSize);},methods: {// 请求用户数据getAccountData(current_page, page_size) {this.loading = true;// GET传参方式this.$http.get(this.$store.state.url.account.list, {'params': {pageSize: page_size,currentPage: current_page,}}).then(({data: data}) => {this.accounts = data['rows'];this.totalCount = data['count'];this.isSupperUserLogin = data['is_superuser'];this.loading = false;}).catch(() => {this.loading = false;});},// 删除指定用户deleteAccount(id) {this.$http.post(this.formatString(this.$store.state.url.account.remove, {id: id,})).then(() => {this.$message.success(this.$store.getters.$lang.messages.successDelete);this.loading = false;this.getAccountData(this.currentPage, this.pageSize);}).catch(() => {this.$message.error(this.$store.getters.$lang.messages.errorDelete);this.loading = false;});},// 提交删除用户onSingleDelete(id) {this.$confirm(this.$store.getters.$lang.messages.confirm,this.$store.getters.$lang.buttons.confirm,{confirmButtonText: this.$store.getters.$lang.buttons.yes,cancelButtonText: this.$store.getters.$lang.buttons.no,type: "warning",}).then(() => {this.deleteAccount(id);});},},
};
</script>

langs/zh.js

需要在columns下增加些配置参数
在这里插入图片描述

is_superuser: '超级用户',
is_staff: '工作人员',
is_active: '状态',
date_joined: '加入时间',
last_login: '最后登录时间',
deployed_user_name: '部署者',
deployed_client_name: '部署主机',
deployed_project_name: '部署项目',
deployed_description: '部署描述',
deployed_at: '部署时间',
priority: '优先级',

store.js

需要在url下增加些配置参数
在这里插入图片描述
在这里插入图片描述

account: {list: "/api/account/list",create: "/api/account/create",info: "/api/account/{id}/info",update: "/api/account/{id}/update",remove: "/api/account/{id}/remove",
},

后端

Paginator

这里我们先了解一下Django的翻页器Paginator

概述

‌DjangoPaginator是一个内置的分页组件,用于将大量数据分页显示,从而改善用户体验并减轻服务器压力‌。使用Paginator可以指定每页显示的数据项数量,并生成一个分页对象,该对象包含了关于总页数、当前页码等信息的方法。

基本用法

‌引入Paginator类‌:首先需要从django.core.paginator模块中引入Paginator类。
‌创建Paginator对象‌:使用Paginator(object_list, per_page)创建一个分页器对象,其中object_list是要分页的数据列表,per_page是每页显示的数据条数。
‌获取页面数据‌:通过调用分页器对象的page(page_number)方法获取特定页面的数据,其中page_number是页码。返回的是一个Page对象,该对象提供了当前页的数据项列表以及其他分页信息,如是否有下一页、上一页等。

代码示例
from django.core.paginator import Paginator# 假设有一个包含100条数据的列表
objects = ['item1', 'item2', ..., 'item100']
# 创建Paginator对象,每页显示10条数据
paginator = Paginator(objects, 10)# 获取第一页的数据
page1 = paginator.page(1)
print(page1.object_list)  # 输出当前页的数据项列表
print(page1.has_next())  # 检查是否有下一页
print(page1.has_previous())  # 检查是否有上一页
print(page1.number)  # 当前页码
属性与方法
  • paginator.count: 总数据项数
  • paginator.num_pages: 总页数
  • paginator.page_range: 一个范围对象,包含所有页码
  • page.object_list: 当前页的数据项列表
  • page.number: 当前页码
  • page.has_next(): 是否有下一页
  • page.has_previous(): 是否有上一页
  • page.next_page_number(): 下一页的页码(如果有的话)
  • page.previous_page_number(): 上一页的页码(如果有的话)

urls.py

新增两个接口映射

url(r'^api/account/list', views.account_list, name='account_list'),
url(r'^api/account/(\d+)/remove', views.account_remove, name='account_remove'),

views.py

导入需要的包

from django.contrib.auth.models import User
from django.core.paginator import Paginator

方法代码开发,具体实现代码有注释

@log_exception()
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def account_list(request):"""account list:param request: request object:return: json"""if request.method == 'GET':# 获取单页页数page_size = int(request.query_params.get('pageSize'))# 拿到当前页current_page = int(request.query_params.get('currentPage'))# 根据主键id顺序排序拿到全部数据对象accounts = User.objects.order_by('id')# 创建翻页器Paginator对象,全部数据 单页页数paginator = Paginator(accounts, page_size)# 提取指定页码的数据page_obj = paginator.get_page(current_page)# model_to_dict:模型数据转字典,定义导出的字段fields = ['id', 'username', 'email', 'is_superuser', 'date_joined', 'last_login', 'is_staff', 'is_active']# 最后拼接数据返回return JsonResponse({'currentPage': current_page, 'pageSize': page_size, 'count': paginator.count,'num_pages': paginator.num_pages, 'is_superuser': request.user.is_superuser,'rows': [model_to_dict(item, fields=fields) for item in page_obj.object_list]})@log_exception()
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def account_remove(request, account_id):"""remove account by account_id:param request: request object:param account_id: account id:return: json"""if request.method == 'POST':# 根据用户id查询并删除User.objects.filter(id=account_id).delete()return JsonResponse({'result': '1'})

运行效果

处理好后,打包Vue代码,重新启动后端服务,刷新浏览器。

在这里插入图片描述

这里留个坑给大家自己实现,就是删除按钮应该给超级管理员隐藏或者不可用,毕竟他要是删了自己账号还管理个啥!

总结

到这里,我们就实现了主页面开发了,接下来将实现其他页面~


http://www.mrgr.cn/news/97360.html

相关文章:

  • 【ARTS】【LeetCode-2873】有序三元组中的最大值!
  • CSS快速上手
  • 手撕LLM(二):从源码出发,探索LoRA加载、推理全流程
  • CentOS Linux升级内核kernel方法
  • rust 同时处理多个异步任务,并在一个任务完成退出
  • 毕业设计:实现一个基于Python、Flask和OpenCV的人脸打卡Web系统(六)
  • Nginx 生产配置文件
  • 数据分析-Excel-学习笔记Day1
  • TYUTJava阶段测试
  • 新一代AI架构实践:数字大脑AI+智能调度MCP+领域执行APP的黄金金字塔体系
  • java发送http请求
  • k8s 1.23升级1.24
  • k8s之Ingress讲解
  • TDengine 从入门到精通(2万字长文)
  • 线程池/内存池/mysql连接池
  • 15分钟完成Odoo18.0安装与基本配置
  • Nginx 常见面试题
  • 现代Web表单验证的终极解决方案:构建可扩展的企业级验证系统
  • sentinel新手入门安装和限流,热点的使用
  • 003集——《利用 C# 与 AutoCAD API 开发 WPF 随机圆生成插件》(侧栏菜单+WPF窗体和控件+MVVM)