8.用户管理专栏主页面开发

news2025/4/8 20:49:50

用户管理专栏主页面开发

  • 写在前面
  • 用户权限控制
  • 用户列表接口设计
  • 主页面开发
    • 前端
      • 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-table
				v-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.coloradmin.cn/o/2329685.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

室内指路机器人是否支持与第三方软件对接?

嘿&#xff0c;你知道吗&#xff1f;叁仟室内指路机器人可有个超厉害的技能&#xff0c;那就是能和第三方软件 “手牵手” 哦&#xff0c;接下来就带你一探究竟&#xff01; 从技术魔法角度看哈&#xff1a;好多室内指路机器人都像拥有超能力的小魔法师&#xff0c;采用开放式…

从代码上深入学习GraphRag

网上关于该算法的解析都停留在大概流程上&#xff0c;但是具体解析细节未知&#xff0c;由于代码是PipeLine形式因此阅读起来比较麻烦&#xff0c;本文希望通过阅读项目代码来解析其算法的具体实现细节&#xff0c;特别是如何利用大模型来完成图谱生成和检索增强的实现细节。 …

【Redis】通用命令

使用者通过redis-cli客户端和redis服务器交互&#xff0c;涉及到很多的redis命令&#xff0c;redis的命令非常多&#xff0c;我们需要多练习常用的命令&#xff0c;以及学会使用redis的文档。 一、get和set命令&#xff08;最核心的命令&#xff09; Redis中最核心的两个命令&…

微前端随笔

✨ single-spa&#xff1a; js-entry 通过es-module 或 umd 动态插入 js 脚本 &#xff0c;在主应用中发送请求&#xff0c;来获取子应用的包&#xff0c; 该子应用的包 singleSpa.registerApplication({name: app1,app: () > import(http://localhost:8080/app1.js),active…

C++中的浅拷贝和深拷贝

浅拷贝只是将变量的值赋予给另外一个变量&#xff0c;在遇到指针类型时&#xff0c;浅拷贝只会把当前指针的值&#xff0c;也就是该指针指向的地址赋予给另外一个指针&#xff0c;二者指向相同的地址&#xff1b; 深拷贝在遇到指针类型时&#xff0c;会先将当前指针指向地址包…

车载诊断架构 --- 整车重启先后顺序带来的思考

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

【C++11(下)】—— 我与C++的不解之缘(三十二)

前言 随着 C11 的引入&#xff0c;现代 C 语言在语法层面上变得更加灵活、简洁。其中最受欢迎的新特性之一就是 lambda 表达式&#xff08;Lambda Expression&#xff09;&#xff0c;它让我们可以在函数内部直接定义匿名函数。配合 std::function 包装器 使用&#xff0c;可以…

Windows 10/11系统优化工具

家庭或工作电脑使用时间久了&#xff0c;会出现各种各样问题&#xff0c;今天给大家推荐一款专为Windows 10/11系统设计的全能优化工具&#xff0c;该软件集成了超过40项专业级实用程序&#xff0c;可针对系统性能进行深度优化、精准调校、全面清理、加速响应及故障修复。通过系…

浅谈在HTTP中GET与POST的区别

从 HTTP 报文来看&#xff1a; GET请求方式将请求信息放在 URL 后面&#xff0c;请求信息和 URL 之间以 &#xff1f;隔开&#xff0c;请求信息的格式为键值对&#xff0c;这种请求方式将请求信息直接暴露在 URL 中&#xff0c;安全性比较低。另外从报文结构上来看&#xff0c…

LightRAG实战:轻松构建知识图谱,破解传统RAG多跳推理难题

作者&#xff1a;后端小肥肠 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 姊妹篇&#xff1a; 2025防失业预警&#xff1a;不会用DeepSeek-RAG建知识库的人正在被淘汰_deepseek-embedding-CSDN博客 从PDF到精准答案&#xff1a;Coze…

C++多线程编码二

1.lock和try_lock lock是一个函数模板&#xff0c;可以支持多个锁对象同时锁定同一个&#xff0c;如果其中一个锁对象没有锁住&#xff0c;lock函数会把已经锁定的对象解锁并进入阻塞&#xff0c;直到多个锁锁定一个对象。 try_lock也是一个函数模板&#xff0c;尝试对多个锁…

垃圾回收——三色标记法(golang使用)

三色标记法(tricolor mark-and-sweep algorithm)是传统 Mark-Sweep 的一个改进&#xff0c;它是一个并发的 GC 算法&#xff0c;在Golang中被用作垃圾回收的算法&#xff0c;但是也会有一个缺陷&#xff0c;可能程序中的垃圾产生的速度会大于垃圾收集的速度&#xff0c;这样会导…

Windows环境下开发pyspark程序

Windows环境下开发pyspark程序 一、环境准备 1.1. Anaconda/Miniconda&#xff08;Python环境&#xff09; 如果不怕包的版本管理混乱&#xff0c;可以直接使用已有的Python环境。 需要安装anaconda/miniconda&#xff08;python3.8版本以上&#xff09;&#xff1a;Anaconda…

SSM婚纱摄影网的设计

&#x1f345;点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345; 项目视频 SS…

1110+款专业网站应用程序UI界面设计矢量图标figma格式素材 Icon System | 1,100+ Icons Easily Customize

1110款专业网站应用程序UI界面设计矢量图标figma格式素材 Icon System | 1,100 Icons Easily Customize 产品特点 — 24 x 24 px 网格大小 — 2px 线条描边 — 所有形状都是基于矢量的 — 平滑和圆角 — 易于更改颜色 类别 &#x1f6a8; 警报和反馈 ⬆️ 箭头 &…

Llama 4 家族:原生多模态 AI 创新的新时代开启

0 要点总结 Meta发布 Llama 4 系列的首批模型&#xff0c;帮用户打造更个性化多模态体验Llama 4 Scout 是有 170 亿激活参数、16 个专家模块的模型&#xff0c;同类中全球最强多模态模型&#xff0c;性能超越以往所有 Llama 系列模型&#xff0c;能在一张 NVIDIA H100 GPU 上运…

正则表达式(Regular Expression,简称 Regex)

一、5w2h&#xff08;七问法&#xff09;分析正则表达式 是的&#xff0c;5W2H 完全可以应用于研究 正则表达式&#xff08;Regular Expressions&#xff09;。通过回答 5W2H 的七个问题&#xff0c;我们可以全面理解正则表达式的定义、用途、使用方法、适用场景等&#xff0c…

JMeter脚本录制(火狐)

录制前准备&#xff1a; 电脑&#xff1a; 1、将JMeter证书导入&#xff0c;&#xff08;bin目录下有一个证书&#xff0c;需要安装这个证书到电脑中&#xff09; 2、按winr&#xff0c;输入certmgr.msc&#xff0c;打开证书&#xff0c;点击下一步&#xff0c;输入JMeter证书…

基于SpringBoot的“高校社团管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“高校社团管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 总体功能结构图 局部E-R图 系统首页页面 用户…

C# Winform 入门(3)之尺寸同比例缩放

放大前 放大后 1.定义当前窗体的宽度和高度 private float x;//定义当前窗体的宽度private float y;//定义当前窗台的高度 2.接收当前窗体的尺寸大小 x this.Width;//存储原始宽度ythis.Height;//存储原始高度setTag(this);//为控件设置 Tag 属性 3.声明方法&#xff0c;获…