Django入门教程——用户管理实现

第六章 用户管理实现

教学目的

  • 复习数据的增删改查的实现。
  • 了解数据MD5加密算法以及实现
  • 模型表单中,自定义控件的使用
  • 中间件的原理和使用

需求分析

系统问题

  • 员工档案涉及到员工的秘密,不能让任何人都可以看到,主要是人事部门进行数据的维护,公司领导具有数据的查看权限。
  • 现在我们开发出来的功能,所有人都可以进行访问,都可以进行数据的修改,不符合需求。

系统功能

  • 管理员用户可以进行用户管理,实现用户的添加、修改、删除等
  • 普通用户可以登录系统,修改个人密码等

用户管理相关数据模型

数据模型设计

在这里插入图片描述

添加用户管理相关数据模型

  1. 添加新的应用python manage.py startapp userinfo

  2. 注册新的应用

    INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','archives','userinfo',
    ]
    
  3. 创建数据模型

    # 用户信息
    class User(models.Model):username = models.CharField(verbose_name='用户账号', max_length=30)password = models.CharField(verbose_name='用户密码', max_length=40)employee = models.ForeignKey(to="archives.Employee", on_delete=models.CASCADE, verbose_name='员工ID', null=True)avatarUrl = models.CharField(verbose_name="头像", max_length=250, null=True, blank=True)role = models.ForeignKey(to="Role", to_field="id", on_delete=models.SET_NULL, verbose_name='角色', null=True)last_login = models.DateTimeField(verbose_name='最后登录时间', auto_now=True)create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)class Meta:db_table = 'sys_user'# 角色
    class Role(models.Model):name = models.CharField(verbose_name='角色名称', max_length=50)remark = models.CharField(verbose_name='备注', max_length=255, null=True, blank=True, )class Meta:db_table = 'sys_role'def __str__(self):return self.name
    
  4. 执行命令创建数据表

    python manage.py makemigrations          
    python manage.py migrate
    

用户的增删改查

  1. 用户列表页面user_list.html

    {%extends 'common/base_list.html'%}
    {% block templet %}
    <!-- 顶部工具栏模板 -->
    <script type="text/html" id="toolbar"><div class="layui-btn-container"><button class="layui-btn  layui-btn-sm" lay-event="add"><i class="layui-icon layui-icon-addition"></i>新增</button></div>
    </script>
    <!-- 表格操作模板 -->
    <script type="text/html" id="TableBar"><div class="layui-clear-space"><a class="layui-btn layui-btn-xs " lay-event="edit"><i class="layui-icon layui-icon-edit"></i>编辑</a><a class="layui-btn layui-btn-xs layui-bg-red" lay-event="delete"><i class="layui-icon layui-icon-delete"></i>删除</a></div>
    </script>
    {%endblock%}
    {% block js %}
    <script>
    layui.use(function(){var $ = layui.jquery,form = layui.form,table = layui.table,layer = layui.layer;// 渲染表格table.render({elem: '#TableId',url: '/user/list/',method:'post',toolbar: '#toolbar',defaultToolbar: ['filter', 'exports', 'print'],cols: [[{type: "checkbox", width: 50},{field: 'index', width: 80, title: '序号',align:'center', sort: true},{field: 'id', width: 80, title: 'ID',align:'center', sort: true,hide:true},{field: 'username', width: 150, title: '用户名',align:'center',sort: true},{field: 'employee', width: 150, title: '姓名',align:'center',sort: true},{field: 'role', width: 150, title: '角色',align:'center',sort: true},{field: 'last_login', width: 150, title: '最近登录',align:'center',sort: true},{title: '操作', minWidth: 240, toolbar: '#TableBar', align: "center", fixed: 'right' }]],limits: [10, 20, 50,100,200,500],limit: 10,page: true,skin: 'row',even: true,});// 头部工具栏事件table.on('toolbar(TableFilter)', function (obj) {if (obj.event === 'add') {layer.open({title: ['新增', 'font-size:18px;font-weight:bold;'],type: 2,shade: 0.3,maxmin:true,shadeClose: true,area: ['60%', '600px'],content: '/user/add/',});}});
    });
    </script>
    {%endblock%}
    
  2. 建立视图函数

    # 用户列表
    @csrf_exempt
    def user_list(request):if request.method == "GET":return render(request,"userinfo/user_list.html")page = request.POST.get('page', 1)limit = request.POST.get('limit', 10)searchParams = request.POST.get('searchParams', None)data_obj = User.objects.all()data_page = Paginator(data_obj, limit).page(page)data_list=[]count = (int(page) - 1) * int(limit)for row in data_page:count += 1item_dict = {}field_names = [field.name for field in row._meta.fields]for field in field_names:if field == "employee":item_dict[field] = row.employee.nameelif field == "role":item_dict[field] = row.role.nameelse:item_dict[field] = getattr(row,field)item_dict["index"]=countdata_list.append(item_dict)return res_json_data.table_api(data=data_list,count=len(data_obj))
    
  3. 建立url路由

    from userinfo import views as user_views
    path("user/list/",user_views.user_list),
    
  4. 建立用户编辑表单类

    class edit_form(forms.ModelForm):class Meta:model = models.Userfields = ['username','role','employee']widgets = {"employee":forms.Select(attrs={"lay-search":""}),}def __init__(self,*args,**kwargs):super().__init__(*args,**kwargs)for name,field in self.fields.items():field.widget.attrs.update({"class":"layui-input","placeholder":"输入"+field.label})
    
  5. 建立添加视图函数

    #settings.py
    DEFAULT_PASSWORD = '123'  # 设置默认密码
    
    from django.conf import settings
    # 用户添加
    def user_add(request):if request.method == "GET":form = user_form.edit_form()return render(request,"userinfo/user_edit.html",{"form":form})form = user_form.edit_form(data=request.POST)if form.is_valid():form.instance.password = settings.DEFAULT_PASSWORDform.save()messages.success(request, '添加成功')return render(request,"userinfo/user_edit.html",{"form":form})print(form.errors)return render(request,"userinfo/user_edit.html",{"form":form})
    
  6. 验证用户名不能重复

    def clean_username(self):username = self.cleaned_data.get("username")user = models.User.objects.filter(username=username).first()if user:raise forms.ValidationError("用户名已存在")return username
    
  7. 控制员工选择框只能选择没有创建用户的人员

    def __init__(self,*args,**kwargs):super().__init__(*args,**kwargs)user_obj = models.User.objects.all()user_id_list = [obj.employee_id for obj in user_obj]self.fields['employee'].queryset = Employee.objects.exclude(id__in=user_id_list)for name,field in self.fields.items():field.widget.attrs.update({"class":"layui-input","placeholder":"输入"+field.label})
    

对数据库中的密码进行加密

MD5简介

MD5加密算法是一种单向加密算法,是不可逆的一种的加密方式。MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

加密实现

  1. 建立encryption.py文件

  2. 建立md5加密算法函数

    import hashlib
    from django.conf import settings
    def MD5(str):obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))obj.update(str.encode('utf-8'))return obj.hexdigest()
    
  3. 修改视图函数

    form.instance.password = MD5(settings.DEFAULT_PASSWORD)
    

实现密码重置

  1. 表格行操作模板

    <!-- 表格操作模板 -->
    <script type="text/html" id="TableBar"><div class="layui-clear-space"><a class="layui-btn layui-btn-xs " lay-event="reset"><i class="layui-icon layui-icon-edit"></i>重置密码</a><a class="layui-btn layui-btn-xs layui-bg-red" lay-event="delete"><i class="layui-icon layui-icon-delete"></i>删除</a></div>
    </script>
    
  2. 建立重置密码视图函数

    # 重置密码
    @csrf_exempt
    def reset_password(request):id = request.POST.get("id") #用户idpassword = MD5(settings.DEFAULT_PASSWORD)User.objects.filter(id=id).update(password=password)return res_json_data.success_api()
    
  3. 通过ajax实现密码重置

    // 单元格事件
    table.on('tool(TableFilter)', function (obj) {var data = obj.data; //获得当前行数据if (obj.event === 'reset') {layer.confirm('确认重置为默认密码吗?', {btn: ['确定', '取消'] //按钮}, function(index){$.post('/user/reset/', {"id":data.id},function(data){if (data.success) {layer.msg(data.msg);}})});}
    });
    

    jQuery get() 和 post() 方法用于通过 HTTP GET 或 POST 请求从服务器请求数据。

    语法:$.get( URL [, data ] [, callback ] [, dataType ] )

    • URL:发送请求的 URL字符串。
    • data:可选的,发送给服务器的字符串或 key/value 键值对(字典)。
    • callback:可选的,请求成功后执行的回调函数。
    • dataType:可选的,从服务器返回的数据类型。默认:智能猜测(可以是xml, json, script, 或 html)。

用户登录的实现

界面原型

在这里插入图片描述

代码实现

  1. 用户登录路由path("",user_views.user_login)

  2. 登录视图函数

    # 用户登录
    def user_login(request):if request.method == "GET":form = user_form.login_form()return render(request,"userinfo/login.html",{"form":form})
    
  3. 用户登录页面模板

    {% load static %}
    <!DOCTYPE html>
    <html>
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>员工信息管理系统</title><link href="{%static 'layui/css/layui.css'%}" rel="stylesheet"><style>body {background:url("{% static 'loginbg.png'%}") 0% 0% / cover no-repeat;font-size:12px;}.main-body {top:50%;left:50%;position:absolute;transform:translate(-50%,-50%);overflow:hidden;width: 428px;background-color: #fff;border-radius:12px;}.login-top {height:117px;background-color:#148be4;border-radius:12px 12px 0 0;font-size:30px;font-weight:400;font-stretch:normal;color:#fff;line-height:117px;text-align:center;overflow:hidden;}.login-top .bg1 {display:inline-block;width:74px;height:74px;opacity:.1;border-radius:0 74px 0 0;position:absolute;left:0;top:43px;background-color: #fff;}.login-top .bg2 {display:inline-block;width:94px;height:94px;opacity:.1;border-radius:50%;position:absolute;right:-16px;top:-16px;background-color: #fff;}.center {width:288px;margin:0 auto;padding-top:40px;padding-bottom:15px;position:relative;}.login-btn {width:288px;height:40px;background-color:#1E9FFF;border-radius:16px;margin:24px auto 0;text-align:center;line-height:40px;color:#fff;font-size:14px;letter-spacing:0;cursor:pointer;border:none;}.center {width:288px;margin:0 auto;padding-top:40px;padding-bottom:15px;position:relative;}</style>
    </head>
    <body><div class="main-body"><div class="login-top"><span>员工信息管理系统</span><span class="bg1"></span><span class="bg2"></span></div></div><script src="{%static 'layui/layui.js'%}"></script>
    <script>
    layui.use(function(){var $ = layui.jquery;var layer = layui.layer;{% for msg in messages %}layer.alert('{{ msg}}');{% endfor %}
    });     
    </script>
    </body>
    </html>
    

    绝对定位布局(position)

    1. 定位方式属性
      • static 默认,元素在文档常规流中当前的布局位置
      • relative :不会脱离文档流,不会浮起来,一般为里面的absolute 元素提供定位依据
      • absolute 元素会被移出正常文档流,相对于上一个绝对定位的父元素来进行定位
      • fixed 元素会被移出正常文档流,相对于屏幕视口(viewport)的位置来指定元素位置
    2. absolute相对定位详解
      • 父元素没有设置相对定位或绝对定位的情况下,元素相对于根元素定位(即html元素)
      • 父元素设置了相对定位或绝对定位,元素会相对于离自己最近的设置了相对或绝对定位的父元素进行定位
    3. 定位属性
      • top样式属性定义了定位元素的上外边距边界与其包含块上边界之间的偏移
      • bottom 定位元素下外边距边界与其包含块下边界之间的偏移
      • left 定位元素的上外边距边界与其包含块上边界之间的偏移
      • right 定位元素的右外边距边界与其包含块右边界之间的偏移
      • transform: translate(12px, 50%); 水平平移,第一个参数对应X轴,第二个参数对应Y轴。如果第二个参数未提供,则默认值为0,注意参数用逗号分隔
  4. 用户登录表单类

    # 登录表单类
    class login_form(forms.ModelForm):class Meta:model =models.Userfields = ['username','password']widgets ={'password':forms.PasswordInput(attrs={"lay-affix":"eye"},render_value=True),}def clean_password(self):password = self.cleaned_data.get("password")return MD5(password)def __init__(self,*args,**kwargs):super().__init__(*args,**kwargs)for name,field in self.fields.items():field.widget.attrs.update({"class":"layui-input","placeholder":"输入"+field.label})
    
    • render_value=True ——保持上次输入的值
  5. 修改视图函数,进行用户登录验证

    # 用户登录
    def user_login(request):if request.method == "GET":form = user_form.login_form()return render(request,"userinfo/login.html",{"form":form})form = user_form.login_form(data=request.POST)if form.is_valid():print(form.cleaned_data,"===校验完成") #打印form提交的所有数据user_obj = User.objects.filter(**form.cleaned_data).first()if not user_obj:messages.warning(request, '用户名或密码错误')return render(request,"userinfo/login.html",{"form":form})# 登录成功return redirect("/employee/list/")print(form.errors)return render(request,"userinfo/login.html",{"form":form})
    

是否登录检验

会话Session

  1. 简介

    Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。

  2. 操作语法

    • 设置session,通过request.session字典

      request.session['user_info'] = {'id':user_obj.id,'user_id':user_obj.id_number,'user_name':user_obj.user_name,'role_id':user_obj.role_id,
      }
      
    • session有效期设置

      request.session.set_expiry(value)

      • 如果value是个整数,session会在设置秒数后失效。
      • 如果value是个datatimetimedelta,session就会在这个时间后失效。
      • 如果value是0,用户关闭浏览器session就会失效。//我们用的就是这种方式
      • 如果value是None,session会依赖全局session失效策略。
    • 获取session值

      后端:user_info = request.session.get('user_info')

      前端:request.session.user_info.name

修改代码实现访问授权

  1. 通过session记录登录用户信息

    # 登录成功
    request.session["user_info"] = {"id":user_obj.id,"username":user_obj.username,"name":user_obj.employee.name,
    }
    request.session.set_expiry(0)
    return redirect("/employee/list/")
    
  2. 用户登录状态验证

    user_info = request.session.get("user_info")
    print(user_info,"==用户信息")
    if not user_info:return redirect("/")
    

中间件

中间件在Django中是一种轻量级、底层的“插件”系统,用于全局地处理请求和响应。它位于Django的请求和响应处理过程之间,可以对HTTP请求和响应进行预处理和后处理,从而实现诸如权限控制、日志记录、数据压缩、缓存等功能。

中间件的请求流程:

在这里插入图片描述

用中间件进行登录验证拦截

  1. 建立auth.py文件,创建中间件类

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import redirect
    from datetime import datetime
    class AuthMiddleware(MiddlewareMixin):def process_request(self, request):print("===访问地址:",request.path,datetime.now())user_info = request.session.get('user_info')print(user_info,"==登陆用户信息")if  user_info:returnreturn redirect("/")
    
  2. 在setting中注册中间件

    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','userinfo.auth.AuthMiddleware',
    ]
    
    • 第9行:注册中间件
  3. 处理302错误,重定向错误

    class AuthMiddleware(MiddlewareMixin):def process_request(self, request):print("===访问地址:",request.path,datetime.now())pass_urls = ['/']if request.path  in pass_urls:returnuser_info = request.session.get('user_info')print(user_info,"==登陆用户信息")if  user_info:returnreturn redirect("/")
    
    • return 没有返回值,将进行放行,否则将进行拦截

注销和密码修改

注销操作

  1. 修改公共模板页面添加用户信息和菜单。

    <li class="layui-nav-item" style="float: right;"><a href="javascript:void(0);"><img src="https://unpkg.com/outeres@0.0.10/demo/avatar/1.jpg" class="layui-nav-img">{{request.session.user_info.name}}</a><dl class="layui-nav-child"><dd><a href="">修改密码</a></dd><dd><a href="/user/logout/">退出</a></dd></dl>
    </li>
    
  2. 添加注销视图函数

    # 用户退出
    def user_logout(request):request.session.clear()return redirect("/")
    

密码修改

  1. 创建单行编辑模版页面single_edit_dlg.html

    {%extends 'common/layout_dlg.html'%}
    {% block css %}
    <style>.layui-input-block{margin-left: 150px; }.layui-form-label{width: 120px;}
    </style>
    {%endblock%}
    {%block content%}
    <div class="layui-card-body"><form class="layui-form"  method="post" novalidate>{% csrf_token %}{% for field in form %}<div class="layui-form-item">{% if field.field.required %}<label class="layui-form-label label-required-next">{{ field.label }}:</label>{% else %}<label class="layui-form-label">{{ field.label }}:</label>{% endif %}<div class="layui-input-block">{{ field }}<span style="color: red">{{ field.errors.0 }}</span></div></div>{% endfor %}<div class="layui-form-item"><div class="layui-input-block"><button type="submit" class="layui-btn" lay-submit>确认提交</button></div></div></form>
    </div>
    {% endblock %}
    {%block js%}
    {% block extendsjs %}{% endblock %}
    {% for msg in messages %}
    <script>layui.use(['layer'], function () {var iconValue = "{{msg.tags}}" == 'success' ? 1 : 2;layer.msg('{{msg}}',{ icon: iconValue, time: 2000 },function (){if( "{{msg.tags}}" == 'success' ){parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页parent.layui.table.reload('TableId');//重新加载父窗口表格}})})
    </script>
    {% endfor %}
    {% endblock %}
    
  2. 创建密码修改表单类

    # 密码修改表单类
    class password_form(forms.ModelForm):confirm_password = forms.CharField(label="确认新密码",required=True,widget=forms.PasswordInput(render_value=True,attrs={"lay-affix":"eye"}))new_password = forms.CharField(label="新密码",required=True,widget=forms.PasswordInput(render_value=True,attrs={"lay-affix":"eye"}))class Meta:model =models.Userfields = ['username','password','new_password','confirm_password']widgets ={'password':forms.PasswordInput(attrs={"lay-affix":"eye"},render_value=True),}def __init__(self,*args,**kwargs):super().__init__(*args,**kwargs)for name,field in self.fields.items():field.widget.attrs.update({"class":"layui-input","placeholder":"输入"+field.label})
    
  3. 完善密码修改视图函数

    # 修改密码
    def change_password(request):if request.method == "GET":form = user_form.password_form()return render(request,"common/single_edit_dlg.html",{"form":form})user_info = request.session['user_info']user_id = user_info['id']row_obj = User.objects.filter(id=user_id).first()form = user_form.password_form(data=request.POST)if form.is_valid():username = form.cleaned_data['username']password = MD5(form.cleaned_data['password'])if row_obj.username != username or row_obj.password!=password:messages.error(request, '用户名或密码不正确')return render(request,"common/single_edit_dlg.html",{"form":form})if form.cleaned_data['new_password']!= form.cleaned_data['confirm_password']:messages.error(request, '两次密码输入不一致')return render(request,"common/single_edit_dlg.html",{"form":form})new_password = MD5(form.cleaned_data['new_password'])User.objects.filter(id=user_id).update(password=new_password)messages.success(request, '修改成功')return render(request,"common/single_edit_dlg.html",{"form":form})return render(request,"common/single_edit_dlg.html",{"form":form})
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/884237.shtml

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

相关文章

BugKu练习记录:矛盾

题目&#xff1a; $num$_GET[num]; if(!is_numeric($num)) { echo $num; if($num1) echo flag{**********}; }关键在于绕过is_numeric&#xff0c;PHP中字符串与数字弱比较&#xff0c;会将字符串转换为数字&#xff0c;截至到非数字字符&#xff0c;如果第一个字符就是非数字…

安宝特分享 | AR技术引领:跨国工业远程协作创新模式

在当今高度互联的工业环境中&#xff0c;跨国合作与沟通变得日益重要。然而&#xff0c;语言障碍常常成为高效协作的绊脚石。安宝特AR眼镜凭借其强大的多语言自动翻译和播报功能&#xff0c;正在改变这一局面&#xff0c;让远程协作变得更加顺畅。 01 多语言翻译优势 安宝特A…

逗号运算符应用举例

在main.cpp里输入程序如下&#xff1a; #include <iostream> //使能cin(),cout(); #include <iomanip> //使能setbase(),setfill(),setw(),setprecision(),setiosflags()和resetiosflags(); //setbase( char x )是设置输出数字的基数,如输出进制数则用set…

vxe-table v4.8+ 与 v3.10+ 虚拟滚动支持动态行高,虚拟渲染更快了

Vxe UI vue vxe-table v4.8 与 v3.10 解决了老版本虚拟滚动不支持动态行高的问题&#xff0c;重构了虚拟渲染&#xff0c;渲染性能大幅提升了&#xff0c;行高自适应和列宽拖动都支持&#xff0c;大幅降低虚拟渲染过程中的滚动白屏&#xff0c;大量数据列表滚动更加流畅。 自适…

ICPC区域赛成都站【赛后回顾+总结】

传送门 前言赛后总结赛后回顾赛后感悟 前言 首先&#xff0c;这是本人本赛季第一场XCPC区域赛&#xff0c;也是本人算竞生涯中第一场XCPC区域赛&#xff08;之前只打过邀请赛和省赛&#xff09;。 赛后总结 然后赛后总结一下&#xff1a;我队天崩开局&#xff0c;我队出师不利…

c盘满了怎么清理垃圾而不误删?6招轻松清理C盘,快来试试

c盘满了怎么清理垃圾而不误删&#xff1f;相信平时工作生活中离不开电脑&#xff0c;随着使用电脑时间就了&#xff0c;C 盘的空间会不断被占据&#xff0c;进而致使系统运行变得迟缓&#xff0c;甚至出现卡顿现象。因此&#xff0c;定期清理 C 盘的是非常重要的。很多电脑小白…

excel的宏1

1宏和vba visual basic for applications 一种编程语言 2vba编写一系列指令的程序&#xff0c;就是宏 3完成重复性的数据任务 点击开发工具 使用设置的宏之后表格的变化 excel帮忙编写了一个代码 以上为自动编写的代码

Swarm-LIO: Decentralized Swarm LiDAR-inertial Odometry论文翻译

文章目录 前言一、介绍二、相关工作三、方法A. 问题表述B. 框架概述C. 群体系统的初始化D. 去中心化激光雷达-惯性状态估计 四. 实验A. 室内飞行B. 退化环境飞行C. 去中心化部署 五. 结论和未来工作 前言 原文&#xff1a;原文 准确的自我状态和相对状态估计是完成群体任务的关…

光耦合器的关键作用和创新---腾恩科技

光耦合器或光隔离器已成为电路中必不可少的器件&#xff0c;它允许信号在无需直接电接触的情况下跨不同电压域传输。这种隔离能力对于保护低压元件免受高压电路的潜在损坏至关重要。本文将仔细研究光耦合器在当今技术中发挥的独特作用&#xff0c;并探讨其在各种应用中不断扩展…

linux:回车换行+进度条+git理解与使用以及如何解决免密码push问题

目录 特殊符号 Linux小程序---进度条 1.\n和\r的理解 2.缓冲区 3.设计简单的倒计时 4.设计简单的进度条 git-版本控制器 1.理解什么是版本控制器? 2.git的使用 3.git的其他说明 总结上传过程 特殊符号 1.(取消显化) 的作用:执行指令,但指令本身不会显化; 举个例子:我…

vscode摸鱼学习插件开发

不知道大家在摸鱼的时候&#xff0c;会不会想要学习&#xff1f; 或者有没有考公人&#xff0c;下班要学习的&#xff1f; 上班时间摸鱼&#xff0c;下班时间不够学习&#xff1f; 为此&#xff0c;我决定开发一个vscode插件&#xff0c;来刷粉笔题 粉笔插件名称&#xff1a;…

如何解决RabbitMQ消息的重复消费问题

什么情况下会导致消息的重复消费——在消费者还没成功发送自动确认机制时发生&#xff1a; 网络抖动消费者挂了 解决方案 每条消息设置一个唯一的标识id幂等方案&#xff1a;【Redis分布式锁、数据库锁&#xff08;悲观锁、乐观锁&#xff09;】 面试官&#xff1a;如何解决…

Kafka 与传统 MQ 消息系统之间有三个关键区别?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka 与传统 MQ 消息系统之间有三个关键区别&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; Kafka 与传统 MQ 消息系统之间有三个关键区别&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 …

软件测试基础知识最强总结(2024版)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、什么是软件&#xff1f; 软件是计算机系统中的程序和相关文件或文档的总称。 二、什么是软件测试&#xff1f; 说法一&#xff1a;使用人工或自动的手段…

智慧用电监控装置:引领0.4kV安全用电新时代

在智能科技日新月异的今天&#xff0c;电力安全与管理正迎来一场前所未有的革新。为0.4kV以下TT、TN系统打造的智慧用电在线监控装置不仅重新定义了电力监控的边界&#xff0c;更为建筑安全用电筑起了一道坚不可摧的防线。 装置集成了单、三相交流电精确测量、四象限电能计量、…

【GL09】(算法)卡尔曼滤波

一、简介 卡尔曼滤波&#xff08;Kalman Filter&#xff09;是一种有效的递归滤波器&#xff08;自回归滤波器&#xff09;&#xff0c;它能够从一系列的包含统计噪声的测量中估计动态系统的状态。卡尔曼滤波广泛应用于信号处理、控制理论、自动驾驶、金融等领域。 基本公式&am…

IIC学习总结

一、基本概念 IIC&#xff08;Inter-Integrated Circuit&#xff09;其实是IICBus简称&#xff0c;所以中文应该叫集成电路总线&#xff0c;它是一种串行通信总线&#xff0c;使用多主从架构。 二、模块结构 I2C串行总线一般有两根信号线&#xff0c;一根是双向的数据线SDA&…

go 聊天系统项目-1

1、登录界面 说明&#xff1a;这一节的内容采用 go mod 管理【GO111MODULE‘’】的模块&#xff0c;从第二节开始使用【GO111MODULE‘off’】GOPATH 管理模块。具体参见 go 包相关知识 1.1登录界面代码目录结构 代码所在目录/Users/zld/Go-project/day8/chatroom/ 1.2登录…

qt QCheckBox详解

QCheckBox 是 Qt 框架中的一个控件&#xff0c;用于创建复选框&#xff0c;允许用户进行选择和取消选择。它通常用于表单、设置界面和任何需要用户选择的场景。 QCheckBox继承自QAbstractButton类&#xff0c;因此继承了按钮的特性。它表示一个复选框&#xff0c;用户可以通过…

使用Postman发送POST请求的指南

作为一名软件测试工程师&#xff0c;掌握如何使用Postman发送POST请求是非常重要的技能。POST请求通常用于向服务器发送数据&#xff0c;以创建或更新资源。本文将详细介绍如何在Postman中发送POST请求&#xff0c;帮助你高效地进行接口测试。 什么是POST请求&#xff1f; PO…