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

Django入门教程——动态表格分页展示数据

第五章 动态表格分页展示数据

教学目的

  • 初步了解layui的使用
  • 理解table组件在layui中的应用
  • 了解数据添加、删除、编辑操作引入JavaScript框架的优势

layUI动态表格

表格组件 table 是 Layui 中使用率极高的一个组件,它以表格的承载方式对数据进行渲染、重载、排序、统计、分页等等一系列交互操作,并提供了丰富的 API 用于扩展,基本涵盖了日常业务所涉及的大部分需求。

表格标签

<table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table>

  • layui-hide类样式,表格标签不显示,表格中没有行列
  • 必须定义表格的id
  • lay-filter layui中表格事件对象标识

表格的渲染

在layui中通过table.render()函数实现表格数据的渲染,常用属性。

  • elem:表格对象ID
  • url:表格数据接口地址
  • method数据查询是通过post还是get
  • toolbar数据表格上部工具栏模板
  • defaultToolbar表格右上角工具图标
  • cols 表格列数组
  • limits数组,表格每页显示数据条数方案
  • limit默认每页显示记录数
  • page 是否开启分页
  • skin设置表格边框风格。可选值:grid|line|row|nob
  • even是否开启隔行背景。

模板定义

基本语法结构:

<script type="text/html" id="toolbar">
<!--html标签-->
</script>

常用的几个事件

  1. 表格事件

    基本语法:table.on('event(filter)', callback);

    • toolbar头部工具栏事件
    • tool单元格工具事件。可在该事件中实现行的更新与删除操作。
  2. 表格方法

    table.reload(id, options, deep) 表格完整重载。

创建动态表格实现数据展示

建立动态表格实现数据展示的模板

  1. 创建数据展示表格的通用模板页面base_list.html

    {%extends 'common/layout.html'%}
    {%block content%}
    <div class="layui-card-body"><!-- 查询操作区一 --><div class="layui-collapse" style="margin-bottom: 10px;"><div class="layui-colla-item"><div class="layui-colla-title">查询</div><div class="layui-colla-content layui-show">{% block query%}{% endblock%}</div></div></div><!-- 表格区域 --><div class="layui-form layui-table-box"><table class="layui-hide" id="TableId" lay-filter="TableFilter"></table></div>
    </div>
    {% block templet %}{% endblock %}
    {% endblock %}
    
    • 模板页面主要有两部分组成,查询区域和表格区域。
    • 新添加了templet模板块,用于动态表格的元素模板的存放。
  2. 修改employ_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: '/employee/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: 'job_number', width: 150, title: '工号',align:'center',sort: true},{field: 'name', width: 150, title: '姓名',align:'center',sort: true},{field: 'depart', width: 150, title: '部门',align:'center',sort: true},{field: 'gender', width: 150, title: '性别',align:'center',sort: true},{field: 'birthday', width: 150, title: '出生日期',align:'center',sort: true},{field: 'phone', width: 150, title: '手机号',align:'center',sort: true},{field: 'hiredate', 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,});
    })
    </script>
    {%endblock%}
    
  3. 运行可以看见基本界面,但是出现数据403错误原因是我们没有提供数据接口。

建立数据接口

  1. 查看页面https://layui.dev/static/json/2/table/demo1.json,可以看见表格数据的基本JSON格式。

  2. 在common文件夹中创建res_json_data.py文件存放JSON数据通用response函数

    # JSON 数据提交通用方法from django.http import JsonResponsedef success_api(msg: str = "成功"):""" 成功响应 默认值”成功“ """res = {'msg': msg,'success': True,}return JsonResponse(res, safe=False)def fail_api(msg: str = "失败"):""" 失败响应 默认值“失败” """res = {'msg': msg,'success': False,}return JsonResponse(res, safe=False)def table_api(msg: str = "success", count=0, data=None, limit=10):""" 动态表格渲染响应 """res = {'msg': msg,'code': 0,'data': data,'count': count,'limit': limit}return JsonResponse(res, safe=False,json_dumps_params={'ensure_ascii': False})# 返回单页数据
    def json_api(code=200,msg="success",data=None):# 包括200(成功)、201(创建)、400(错误请求)、401(未授权)、403(禁止)、404(未找到)、500(服务器错误)res={"code": code,"message": msg,"data": data}return JsonResponse(res, safe=False, json_dumps_params={'ensure_ascii': False})# 返回多页数据
    def json_list_api(code=200,msg="success",data=None,total=0,limit=10, page=1):res={"code": code,"message": msg,"data": {'total': total,'limit': limit,'page': page,'data': data}}return JsonResponse(res, safe=False,json_dumps_params={'ensure_ascii': False})
    
  3. 改造视图函数

    # 员工数据表格
    def employee_list(request):print(request.method,"==请求方式")if request.method == "GET":return render(request,"archives/employee_list.html")
    

    出现错误:CSRF token missing or incorrect,错误原因是ajax的post提交没有进行CSRF验证。

  4. 解决ajax提交不进行CSRF验证

    from django.views.decorators.csrf import csrf_exempt
    @csrf_exempt
    def  viewfun(request)
    
    1. 导入csrf_exempt
    2. 在ajax请求的视图函数上面加上@csrf_exempt注解(装饰器)。
  5. 改造视图函数,对POST请求返回表格需要的JSON格式数据。

    # 员工数据表格
    @csrf_exempt
    def employee_list(request):print(request.method,"==请求方式")if request.method == "GET":return render(request,"archives/employee_list.html")# post请求返回JSONdata_obj = Employee.objects.all()data_list=[]for row in data_obj:data_list.append({"id":row.id,"name":row.name,"job_number":row.job_number,"phone":row.phone,})return res_json_data.table_api(data=data_list)
    

    分析这个程序在效率方面,主要是对JSON字典的创建,比较麻烦。

  6. 优化JSON字典的创建

    Model._meta.fields :返回模型字段对象列表

    # post请求返回JSON
    data_obj = Employee.objects.all()
    row_obj = data_obj[0]
    print(row_obj._meta.fields)
    field_names = [field.name for field in row_obj._meta.fields]
    print("==字段列表:",field_names)
    
    • ⑤行:采用列表推导式,生成一个列表
  7. 改造视图函数

    # post请求返回JSON
    data_obj = Employee.objects.all()
    data_list=[]
    for row in data_obj:item_dict = {}field_names = [field.name for field in row._meta.fields]for field in field_names:item_dict[field] = getattr(row,field)data_list.append(item_dict)
    return res_json_data.table_api(data=data_list)
    

    getattr(row,field):内置函数,等同于row.field

  8. 解决返回对象的错误

    for field in field_names:if field == "depart":item_dict[field] = row.depart.nameelse:item_dict[field] = getattr(row,field)
    
  9. 解决性别显示错误问题

    for field in field_names:if field == "depart":item_dict[field] = row.depart.nameelif field == "gender":item_dict[field] = row.get_gender_display()else:item_dict[field] = getattr(row,field)
    

数据分页和排序

  1. 批量向人员表格中添加数据。

    def index(request):for i in range(100):new_data ={'name':f"员工{i}",'job_number':f"RS0{i}",'gender':1,'birthday':'2018-08-11','hiredate':datetime.now(),'depart':Department.objects.first(),}# Employee.objects.create(**new_data)employee =Employee(**new_data)employee.save()return HttpResponse("<h1 style='color:red'>我的第一个Django视图</h1>")
    
    • 12行:用到了**对字典进行解包
    • 11行:可以通过create向数据库中插入元素
    • 12行,13行:通过创建一个模型对象,然后调用模型对象的save()方法保存到数据库中。注意:如果这里对象是存在的对象,save()方法将执行更新update操作,否则执行insert操作。
  2. 排序和分页的相关语法。

    排序:

    • 升序:实体模型.objects.all().order_by("排序字段1","排序字段2")
    • 降序:实体模型.objects.all().order_by("-排序字段")

    分页:

    Paginator 类用于对列表进行分页,它允许你将对象列表分成固定长度的页。

    语法 : Paginator(列表对象,每页数量)

    返回当前页数据 : page = paginator.page(页码)

  3. 改造视图函数实现排序和分页

    from django.core.paginator import Paginator
    page = request.POST.get('page', 1)limit = request.POST.get('limit', 10)data_obj = Employee.objects.all()data_page = Paginator(data_obj, limit).page(page)data_list=[]for row in data_page:item_dict = {}field_names = [field.name for field in row._meta.fields]……return res_json_data.table_api(data=data_list,count=len(data_obj))
    
  4. 改造新增操作

    // 工具栏事件
    table.on('toolbar(TableFilter)', function (obj) {if (obj.event === 'add') {window.location.href = '/employee/add/';}
    });
    

    基本语法:table.on('event(filter)', callback);

    • toolbar头部工具栏事件
    • tool单元格工具事件。可在该事件中实现行的更新与删除操作。
  5. 改造数据排序

    data_obj = Employee.objects.all().order_by('-id')
    
  6. 改造编辑操作

    // 单元格事件
    table.on('tool(TableFilter)', function (obj) {var data = obj.data; //获得当前行数据if (obj.event === 'edit') {window.location.href = '/employee/edit/'+data.id+'/';}
    });
    
  7. 删除员工操作

    // 单元格事件
    table.on('tool(TableFilter)', function (obj) {var data = obj.data; //获得当前行数据if (obj.event === 'edit') {window.location.href = '/employee/edit/'+data.id+'/';}else if (obj.event === 'delete') {layer.confirm('确认删除吗?', {btn: ['确定', '取消'] //按钮}, function(index){console.log('点击了确定');layer.close(index);window.location.href = '/employee/delete/'+data.id+'/';});}
    });
    
    # 员工删除
    def employee_del(request,nid):Employee.objects.filter(id=nid).delete()return redirect("/employee/list/")
    

数据查询操作

查询语句基本语法

基本语法
  1. filter(**kwargs)

​ 返回一个新的 QuerySet,包含的对象满足给定查询参数。

  1. exclude(**kwargs)

​ 返回一个新的 QuerySet,包含的对象不满足给定查询参数。

表示并且关系查询
# 方法一:
UserInfo.objects.filter(name="张晓红",age=39).all()# 方法二:
data_dict ={"name":"张晓红","age":39}
UserInfo.objects.filter(**data_dict).all()
表示或者关系查询
from django.db.models import Q
# 假设我们有一个 Employee 模型,部门和头衔都是外键,你可以直接使用外键字段
employees = Employee.objects.filter(Q(department__name='研发部') | Q(department__name='市场部'),Q(title__name='工程师') | Q(title__name='经理')
)

我们使用了 Q 对象来构建两个查询条件,每个条件都包含一个逻辑或操作。第一个查询条件检查 department 字段是否等于“研发部”或“市场部”,第二个查询条件检查 title 字段是否等于“工程师”或“经理”。

查询比较运算符
数字类型查询比较
  • 等于:data_list = UserInfo.objects.filter(age=26)
  • 大于:data_list = UserInfo.objects.filter(age__gt=26)
  • 大于等于:data_list = UserInfo.objects.filter(age__gte=26)
  • 小于:data_list = UserInfo.objects.filter(age__lt=28)
  • 小于等于:data_list = UserInfo.objects.filter(age__lte=28)
  • 不等于:data_list = UserInfo.objects.exclude(age=28)
  • 在列表中 :order_obj = Order.objects.filter(id__in=orderID_list).order_by('-update_time')
字符串比较
  • 等于:data_list = UserInfo.objects.filter(name="张晓红")
  • 不等于:data_list = UserInfo.objects.filter(name__ne="张晓红")
  • 以XX开头:data_list = UserInfo.objects.filter(name__startswith="刘")
  • 以XX结尾:data_list = UserInfo.objects.filter(name__endswith="红")
  • 包含XX:data_list = UserInfo.objects.filter(name__contains="小")
查询语句举例
  1. 查询所有性别为女的员工

    def index(request):data_obj = Employee.objects.filter(gender=2).all()res_list = [item.name for item in data_obj]print(res_list)return HttpResponse("<h1 style='color:red'>我的第一个Django视图</h1>")
    
  2. 查询销售部的所有员工

    data_obj = Employee.objects.filter(depart__name='销售部').all()
    
    data_obj = Employee.objects.filter(depart_id=5).all()
    
  3. 查询2018-1-1日之前出生的员工

    data_obj = Employee.objects.filter(birthday__lt="2018-1-1").all()
    
  4. 查询2018-1-1日之前出生的女员工

    data_obj = Employee.objects.filter(birthday__lt="2018-1-1",gender=2).all()
    
  5. 查询姓名中包含李的员工

    data_obj = Employee.objects.filter(name__contains="李").all()
    

查询操作改造

  1. 创建员工信息查询表单类

    class employee_seacher_form(forms.ModelForm):class Meta:model = Employeefields = ['name','gender','depart','job_number','phone']def __init__(self,*args,**kwargs):super().__init__(*args,**kwargs)for name,field in self.fields.items():field.widget.attrs={"class":"layui-input","placeholder":"输入"+field.label}field.required = False
    

    field.required = False 设置所有字段都不是必须输入字段

  2. 改造视图函数

    # 员工数据表格
    @csrf_exempt
    def employee_list(request):print(request.method,"==请求方式")if request.method == "GET":init_data ={"gender":0}form =employee_form.employee_seacher_form(initial=init_data)return render(request,"archives/employee_list.html",{"form":form})
    
  3. 改造模板页面

    {% block query%}
    <form class="layui-form" novalidate><div class="layui-form-item">{% for field in form %}<div class="layui-inline"><label class="layui-form-label w-auto">{{ field.label }}: </label><div class="layui-input-inline">{{ field }}</div></div>{% endfor %}<div class="layui-inline" style="float: right;"><div class="layui-input-inline" style="width: auto;"><button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="data-search-btn"id="search"><i class="layui-icon layui-icon-search"></i>查 询</button><button class="layui-btn layui-btn-primary"><i class="layui-icon layui-icon-refresh"></i> 重置</button></div></div></div>
    </form>
    {%endblock%}
    
  4. 查询事件的处理

    // 监听搜索操作
    form.on('submit(data-search-btn)', function (data) {console.log(data.field)var result = JSON.stringify(data.field);//执行搜索重载table.reload('TableId', {page: {curr: 1},where: {searchParams: result}}, 'data');return false;
    });
    
    • JSON.stringify():将 JavaScript 对象或值转换为 JSON 格式的字符串。
    • data.field :layui表单方法,可以获取表单中所有控件的值
  5. 查询函数的改造

    import json# post请求返回JSON
    page = request.POST.get('page', 1)
    limit = request.POST.get('limit', 10)
    searchParams = request.POST.get('searchParams', None)
    if searchParams:searchParams =json.loads(searchParams)fileld_names = list(searchParams.keys())fileld_vaules = list(searchParams.values())filter_dict = dict()for i in range(len(fileld_vaules)):if fileld_vaules[i]:item = fileld_names[i]+"__contains"filter_dict[item] = fileld_vaules[i]print(filter_dict,"==查询参数")data_obj = Employee.objects.filter(**filter_dict).order_by('-id')
    else:data_obj = Employee.objects.all().order_by('-id')
    data_page = Paginator(data_obj, limit).page(page)
    

    json.loads() 是 Python 的标准库模块 json 中的一个函数,用于将 JSON 格式的字符串解码成 Python 字典对象。

  6. 修改部门查询错误问题

    for i in range(len(fileld_vaules)):if fileld_vaules[i]:if fileld_names[i] == "depart":item = fileld_names[i]+"_id"else:item = fileld_names[i]+"__contains"filter_dict[item] = fileld_vaules[i]
    

优化编辑删除等操作

弹出层组件

弹出层组件 layer 是 Layui 最古老的组件,也是使用覆盖面最广泛的代表性组件。 layer 集众多弹层功能为一体,灵活而多样,是许多开发者的网页弹出层的首选交互方案,在各类业务场景都能发挥重要作用。

layer.open({title: ['编辑', 'font-size:18px;font-weight:bold;'],type: 2,shade: 0.3,maxmin:true,shadeClose: true,area: ['60%', '400px'],content: url+"?id="+data.id,
});

上面函数可以弹出一个iframe页面层。

  • title:弹出层的标题
  • type:弹层类型,2,为 iframe 内联框架层
  • shade:弹层的遮罩。shade: 0.3 设置遮罩深色背景的透明度;shade: [0.3, '#FFF'] 设置遮罩透明度和颜色值;shade: 0 不显示遮罩
  • maxmin:是否开启标题栏的最大化和最小化图标。
  • shadeClose:是否点击遮罩时关闭弹层。当遮罩存在时有效。
  • area:设置弹层的宽高
  • content:弹层内容。若 type: 2(iframe 层)则为url地址

具体操作

  1. 改造模板编辑函数

    if (obj.event === 'edit') {layer.open({title: ['编辑', 'font-size:18px;font-weight:bold;'],type: 2,shade: 0.3,maxmin:true,shadeClose: true,area: ['60%', '400px'],content: '/employee/edit/'+data.id+'/',});
    }
    
  2. 解决拒绝链接请求的错误

    settings.py中添加

    X_FRAME_OPTIONS = 'SAMEORIGIN'  # 设置Frame-Options为SAMEORIGIN,否则无法在iframe中加载页面
    

    X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在 frame , iframe 或者 object 中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。

    X-Frame-Options有三个可能的值:

    • deny 表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
    • sameorigin 表示该页面可以在相同域名页面的 frame 中展示。
    • allow-from uri(http://......) 表示该页面可以在指定来源的 frame 中展示。
  3. 创建对话框公共模板页面layout_dlg.html

    {% load static %}
    <!DOCTYPE html>
    <html>
    <head><meta charset="utf-8"><title>layui</title><meta name="renderer" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0"><link href="{%static 'layui/css/layui.css'%}" rel="stylesheet" media="all">{% block css %}{% endblock %}<style>/* 必须字段 */.label-required-next:after {top: 6px;right: 5px;color: red;content: '*';position: absolute;margin-left: 4px;font-weight: 700;line-height: 1.8em;}/* 只读文本框 */.readonly-input {background-color: #f2f2f2;border: 1px solid #d2d2d2;}</style>
    </head>
    <body style="background-color: #FFF;">
    <div class="layui-form">{% block content %}{% endblock %}
    </div>
    <script src="{%static 'layui/layui.js'%}"></script>
    {% block js %}{% endblock %}
    </body>
    
  4. 创建两行编辑模板

    {%extends 'common/layout_dlg.html'%}
    {%block content%}
    <div class="layui-card-body"><form class="layui-form"  method="post" novalidate><div class="layui-form-item">{% csrf_token %}{% for field in form %}<div class="layui-inline">{% 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-inline layui-input-wrap">{{ field }}<span style="color: red">{{ field.errors.0 }}</span></div></div>{% endfor %}</div><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 %}
    
    • layui-row layui-col-xs6是Layui 栅格系统,采用业界比较常用的容器横向 12 等分规则
    • layer.getFrameIndex(window.name);在 iframe 页中获取弹层索引
    • layer.close(index, callback);关闭弹层。参数 index 打开弹层时返回的唯一索引;参数 callback 关闭弹层后的回调函数
  5. 改造编辑视图函数,进行提醒和关闭对话框

    from django.contrib import messages
    ……
    if form.is_valid():form.save()messages.success(request, '编辑成功')return render(request,"archives/employee_add.html",{"form":form})
    ……
    

    返回错误信息

    • 方法一 : 通过form对象附加到下相应的字段上

      if form.is_valid():# 获取输入的验证码,并从form中移除input_captcha = form.cleaned_data.pop('captcha')captcha_code = request.session.get('code','')request.session["code"] = None  # 验证码验证后,移除session中的验证码if captcha_code.upper() != input_captcha.upper():form.add_error("captcha","验证码错误")return render(request,'login/login.html',{"form":form})
      
    • 方法二 : 通过Message进行传递

      #views
      from django.contrib import messages
      messages.warning(request, '用户名或密码错误')
      
      #html
      {% for msg in messages %}layer.alert('{{ msg}}');
      {% endfor %}
      

    django.contrib.messages详解

    后端传递消息的方法:

    • messages.debug(request, '消息1')将在生产部署中被忽略(或删除)的与开发相关的消息
    • messages.info(request, '消息2')为用户提供信息消息
    • messages.success(request, '消息3')行为成功消息
    • messages.warning(request, '消息4')失败并没有发生,但可能即将发生
    • messages.error(request, '消息5')一个操作没有成功,或者发生了其他一些失败

    前端将通过messages列表对象传递消息

    • 可以通过message.tags拿到每个消息
    • 通过message拿到具体的消息
  6. 改造列表数据生成记录编号

    ……
    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]……
    
  7. 改造查询选择框选择后自动执行查询

    1. 修改查询表单

      class employee_seacher_form(forms.ModelForm):class Meta:model = Employeefields = ['name','gender','depart','job_number','phone']widgets = {"gender":forms.Select(attrs={"lay-filter":"select-filter"}),"depart":forms.Select(attrs={"lay-filter":"select-filter"}),}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})
      
      • 通过模式表单的widgets属性给选择框添加lay-filter属性
      • 改造初始化函数属性采用update方法,避免覆盖。
    2. 添加选择框事件

      //监听选择框搜索事件
      form.on('select(select-filter)', function(data){$("#search").click()
      });
      

      通过Jquery方法调用查询按钮的单击事件

      layui选择框事件:form.on('select(filter)', callback);

      • select 为选择框事件固定名称
      • filter 为选择框元素对应的 lay-filter 属性值

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

相关文章:

  • CSS中为特定的元素设置背景图片(Top1,Top1,Top3)
  • springboot095学生宿舍信息的系统--论文pf(论文+源码)_kaic
  • openEuler 逻辑卷操作案例
  • 图像处理 -- 白平衡处理简介
  • Android token JJWT
  • 字节流读写复制视频 JAVA
  • Java版本的基于计算机视觉的跃动小子保卫主公自动通关计划之整体思路篇
  • 创建和管理IPAM
  • Kubernetes:(二)K8Sv1.20二进制部署
  • Lesson12---queue
  • 字节跳动在欧洲设立AI研发中心
  • 如何将 Excel 数据转换为 SQL 脚本:基于 Java 的全面解析
  • MySQL Workbench安装教程(Windows)
  • R语言生物群落(生态)数据统计分析与绘图
  • JAVA基础:IO流 (学习笔记)
  • 【题解】—— LeetCode一周小结43
  • 关于我的数据库——MySQL——第五篇
  • 【隐私计算篇】全同态加密应用场景案例(隐私云计算中的大模型推理、生物识别等)
  • 详细分析Pytorch中的permute基本知识(附Demo)
  • 一文读懂高考志愿专业名词,让你的志愿填报不再迷茫
  • 【Spring知识】Spring Starter内核spring.factories的工作机制
  • [专有网络VPC]ECS安全组配置案例
  • 单纯形线性规划
  • 合合信息智能文档处理百宝箱:强力驱动,加速文档类应用研发进程
  • 开源自动化测试工具Playwright
  • C#与C++交互开发系列(十四):C++中STL容器与C#集合传递的形式