Python入门自学进阶-Web框架——26、DjangoAdmin项目应用-数据记录操作

news2025/8/10 11:19:29

对于每个表显示的数据,点击其中一条,进入这条数据的修改页面,显示此条数据的具体内容,并提供修改、删除等功能。主要是ModelForm的应用。

一、记录数据修改

首先是路由项的添加,点击一条记录后,进入相应的记录显示修改页面:

urls.py中增加路由项:path('<str:app_name>/<str:table_name>/<int:id_num>/change/',views.rec_obj_change,name='rec_change'),

视图函数中增加对应的函数rec_obj_change:

def rec_obj_change(req,app_name,table_name,id_num):
    print(app_name,table_name,id_num)
    return render(req,'mytestapp/rec_change.html')

模板中增加rec_change.html:

{% extends 'base.html' %}
{% load tags %}
{% block mybody %}
<body>
    <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
        <a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">我的客户管理系统</a>
        <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse" data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <ul class="navbar-nav px-3">
            <li class="nav-item text-nowrap">
                <a class="nav-link" href="#">{{ request.user.userprofile.name }}</a>
            </li>
        </ul>
    </nav>
    <div class="container-fluid" style="margin-top: 20px;">
        <div class="flex-column bd-highlight">
            <div class="p-3 mb-2 bg-info text-white">数据表:</div>
            <div class="p-2 mb-2">数据项111</div>
        </div>
    </div>
</body>
{% endblock %}

在前一步骤显示数据的基础上,将数据的第一列增加上a标签,最终形成<str:app_name>/<str:table_name>/<int:id_num>/change/格式的href,跳转到rec_change.html页面。

首先改造数据显示列表,将第一列做成a标签:

@register.simple_tag
def build_table_row(obj,admin_class,url_path):
    row_ele = ""
    print("===///:::",obj)
    for row_data in obj:
        row_ele = row_ele +"<tr>"
        for index_ele,column in enumerate(admin_class.list_display):
            field_obj = row_data._meta.get_field(column)
            if field_obj.choices:
                column_data = getattr(row_data,"get_%s_display"%column)()
            else:
                column_data = getattr(row_data,column)
            field_obj1 = getattr(row_data,column)
            if hasattr(field_obj1,'values'):
                s = ""
                dic1 = field_obj1.values()[0]
                print(type(dic1),dic1)
                for v in dic1.values():
                    s = s + str(v) + ';'
                column_data = s
            if index_ele == 0:   # 若果是第一列,则加上a标签,可以跳转到修改页
                row_ele += '<td colspan="6"><a href="%s%s/change/">%s</a></td>'%(url_path,row_data.id,column_data)
            else:
                row_ele += "<td colspan='6'>%s</td>"%column_data
        row_ele = row_ele + "</tr>"
    print(row_ele)
    return mark_safe(row_ele)

在遍历admin_class中的list_display时,使用enumerate,生成index及数据,对于index为0的,即显示数据的第一列加上a标签,a标签的href为mytestapp/customer/3/change/格式,其中3是id的值。这样,点击对应的数据的第一列,就进入rec_change.html页。

rec_change.html页对每条记录的数据进行详细显示,并提供修改、验证功能。

修改、验证用到前面学过的ModelForm类,自动生成前端标签,提供基本的验证功能。

温习一下ModelForm:

class CustomerModelForm(forms.ModelForm):
    class Meta:
        model = models.Customer
        fields = "__all__"
def rec_obj_change(req,app_name,table_name,id_num):
    print(app_name,table_name,id_num)
    obj = CustomerModelForm()
    return render(req,'mytestapp/rec_change.html',{'obj':obj})

前端将“数据项111”改成{{ obj }},将显示如下

 先定义CustomerModelForm类,在视图函数中生成这个类的实例,返回给前端,前端就能自动生成对应的标签,并具有基本的验证功能。ModelForm类主要是指定Meta中的model以及fields。

因为我们是针对所有的Model类,即所有的表都会进行数据修改,不能定义一个Model,就定义一个ModelForm,这里要动态生成ModelForm。

def create_model_form(req,admin_class):
    # 动态生成ModelForm类,主要使用type函数
    class Meta:
        model = admin_class.model
        fields = "__all__"
    model_form_class = type("DynamicModelForm",(ModelForm,),{'Meta':Meta})
    # setattr(model_form_class,'Meta',Meta)  # 以这种方式给动态生成的类加Meta不好用
    return model_form_class
def rec_obj_change(req,app_name,table_name,id_num):
    admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    model_form_class = myutils.create_model_form(req,admin_class)
    obj = admin_class.model.objects.get(id = id_num)
    form_obj = model_form_class(instance=obj)
    return render(req,'mytestapp/rec_change.html',{'obj':form_obj})

前端:

<div class="container-fluid" style="margin-top: 20px;">
        <div class="flex-column bd-highlight">
            <div class="p-3 mb-2 bg-info text-white">数据表:</div>
            <div class="p-2 mb-2">
                {{ obj.as_ul }}
            </div>
        </div>
    </div>

{{ obj.as_ul }}显示:

 美化一下:

<div class="form-group row">
     {% for f in obj %}
     <label for="inputPassword" class="col-sm-2 col-form-label">{{ f.label }}</label>
         <div class="col-sm-10">
              {{ f }}
         </div>
     {% endfor %}
</div>

将上述字段包入form标签中,并增加修改保存按钮:

<form role="form" method="post">{% csrf_token %}
      <div class="form-group row">
           {% for f in obj %}
                  {% if f.field.required %}  <!-- 字段是否必填,如果必填,标签加粗显示 -->
                       <label class="col-sm-2 col-form-label"><b>{{ f.label }}</b></label>
                  {% else %}
                       <label class="col-sm-2 col-form-label">{{ f.label }}</label>
                  {% endif %}
                  <div class="col-sm-10">
                       {{ f }}
                  </div>
            {% endfor %}
        </div>
        <div class="form-group row" style="float: right;margin-right: 100px">
             <div class="col-sm-10  pull-right">
                  <button type="submit" class="btn btn-success pull-right">Save</button>
             </div>
        </div>
</form>

 使用post方法提交到本页面,后端进行修改保存

 后端修改:

def rec_obj_change(req,app_name,table_name,id_num):
    admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    model_form_class = myutils.create_model_form(req,admin_class)
    obj = admin_class.model.objects.get(id=id_num)
    if req.method == "POST":
        form_obj = model_form_class(req.POST,instance=obj)
        # ModelForm参数为一个时,是新建一条记录,当有两个参数时,就是修改
        # POST方法就是进行记录修改的,所以需要两个参数,第二个是instance=参数
        if form_obj.is_valid():
            form_obj.save()
    else:    # 这是GET请求,所以是新建一个ModelForm,进行显示
        form_obj = model_form_class(instance=obj)
    return render(req,'mytestapp/rec_change.html',{'obj':form_obj})

在生成ModelForm时,就对相关字段添加前端生成标签时的样式进行设置,即进行class属性设置:

def create_model_form(req,admin_class):
    # 动态生成ModelForm类,主要使用type函数
    def __new__(cls, *args, **kwargs):
        # 対生成ModelForm中的字段添加前端样式,即在前端自动生成标签时带上class属性
        cls.base_fields['qq'].widget.attrs['class'] = 'form-control'
        return ModelForm.__new__(cls)
    class Meta:
        model = admin_class.model
        fields = "__all__"
    model_form_class = type("DynamicModelForm",(ModelForm,),{'Meta':Meta})
    setattr(model_form_class,'__new__',__new__)  # 以这种方式给动态生成的类加__new__方法
    return model_form_class

base_fields是所有字段的列表。

二、记录数据增加

修改数据显示前端文件,增加一个Add标签:

<div class="p-3 mb-2 bg-info text-white">表数据管理: {{ model_class_name }}
            <div style="float: right"><a class="pull-right" href="{{ url_path }}add/">Add</a> </div>
        </div>

增加路由项:

path('<str:app_name>/<str:table_name>/add/',views.rec_obj_add,name='rec_add'),

增加视图函数rec_obj_add:

def rec_obj_add(req,app_name,table_name):
    admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    model_form_class = myutils.create_model_form(req, admin_class)
    if req.method == "POST":
        form_obj = model_form_class(req.POST)
        # ModelForm参数为一个时,是新建一条记录,POST方法提交,是新建一条记录
        if form_obj.is_valid():
            form_obj.save()
            return redirect(req.path.replace("/add/","/")
    else:    # 这是GET请求,所以是新建一个空ModelForm
        form_obj = model_form_class()
    return render(req,"mytestapp/rec_add.html",{'obj':form_obj,'model_name':admin_class.model.__name__})

前端显示页面rec_add.html:

{% extends 'base.html' %}
{% load tags %}
{% block mybody %}
<body>
    <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
        <a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">我的客户管理系统</a>
        <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse" data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <ul class="navbar-nav px-3">
            <li class="nav-item text-nowrap">
                <a class="nav-link" href="#">{{ request.user.userprofile.name }}</a>
            </li>
        </ul>
    </nav>
    <div class="container-fluid" style="margin-top: 20px;">
        <div class="flex-column bd-highlight">
            <div class="p-3 mb-2 bg-info text-white">数据表:{{ model_name }}  ————数据添加</div>
            <div class="p-2 mb-2" style="margin-left: 30px">{{ obj.errors }}</div>
            <div class="p-2 mb-2" style="margin-left: 30px">
                <form role="form" method="post">{% csrf_token %}
                    <div class="form-group row">
                        {% for f in obj %}
                            {% if f.field.required %}
                                <label class="col-sm-2 col-form-label"><b>{{ f.label }}</b></label>
                            {% else %}
                                <label class="col-sm-2 col-form-label">{{ f.label }}</label>
                            {% endif %}
                                <div class="col-sm-10">
                                    {{ f }}
                                </div>
                        {% endfor %}
                    </div>
                    <div class="form-group row" style="float: right;margin-right: 100px">
                        <div class="col-sm-10  pull-right">
                            <button type="submit" class="btn btn-success pull-right">Save</button>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
</body>
{% endblock %}

 

三、记录数据修改、增加中多选下拉框不同样式设计

在Django的admin应用中,如果配置了filter_horizontal = ['tags'],则显示如下的样式:

 自己实现类似的功能。

首先在admin_class类中增加配置filter_horizontal = ['tags']

在前端显示表字段时,要进行判断,即如果字段值在filter_horizontal中,就要使用上述的格式显示。

首先要写两个标签,来获取多选下拉框中没有被选中的项和已经选中的项的数据集:

@register.simple_tag
def get_m2m_obj_list(admin_class,f):  # 获取没有被选择的所有项
    field_obj = getattr(admin_class.model,f.name)
    all_obj_list = field_obj.rel.model.objects.all()
    selected_list = f.initial
    print('================================all=======')
    print(all_obj_list)
    print('=========================selected=======')
    print(selected_list)
    noselect_list = []
    for obj in all_obj_list:
        if obj not in selected_list:
            noselect_list.append(obj)

    return noselect_list

@register.simple_tag
def get_m2m_selected_list(form_obj,f):    # 获取所有已选择的项
    selected_obj = getattr(form_obj.instance,f.name)
    print(selected_obj.all())
    return selected_obj.all()

前端循环,填充进入不同的下拉框:

<div class="p-2 mb-2" style="margin-left: 30px">
                <form role="form" method="post">{% csrf_token %}
                    <div class="form-group row">
                        {% for f in form_obj %}
                            {% if f.field.required %}
                                <label class="col-sm-2 col-form-label"><b>{{ f.label }}</b></label>
                            {% else %}
                                <label class="col-sm-2 col-form-label">{{ f.label }}</label>
                            {% endif %}
                                <div class="col-sm-10" style="padding-top: 5px">
                                    <div class="row">
                                    {% if f.name in admin_class.filter_horizontal %}
                                        <div class="col-md-2" >
                                            {% get_m2m_obj_list admin_class f as m2m_obj_list %}
                                             <select id="mynoselect" multiple class="select-box">
                                                 {% for obj in m2m_obj_list %}
                                                     <option value="{{ obj.id }}">{{ obj }}</option>
                                                 {% endfor %}
                                             </select>
                                        </div>
                                        <div class="col-md-1">
                                            ===》<br>
                                            《===
                                        </div>
                                        <div class="col-md-2">
                                             <select id="myselected" multiple class="select-box">>
                                                {% get_m2m_selected_list form_obj f as selected_list %}
                                                 <!-- 上面是使用自定义标签获取已选择项数据-->
                                                 <!-- 下面是经过测试,使用f的initial也能获取到,不需要再定义标签 -->
                                                 {% for obj in f.initial %}
                                                    <option value="{{ obj.id }}">{{ obj }}</option>
                                                 {% endfor %}
                                             </select>
                                        </div>
                                    {% else %}
                                            {{ f }}
                                    {% endif %}
                                    </div>
                                </div>
                        {% endfor %}
                    </div>
                    <div class="form-group row" style="float: right;margin-right: 100px">
                        <div class="col-sm-10  pull-right">
                            <button type="submit" class="btn btn-success pull-right">Save</button>
                        </div>
                    </div>
                </form>
            </div>

关键点是如何将对应记录的多选下拉框填充上正确的数据,model类的字段的rel.model属性指向字段关联的外键表对应的model,通过这个model,即可查询出下拉框的所有数据,在此基础上,找出未选择和已选择数据。ModelForm每个字段的initial属性,也指出了已选择的数据,可以直接在前端使用。最终样式:

数据填上后,就是要前端实现双击数据实现数据在两个多选下拉框之间移动,这主要是前端技术,与python就无关了:

<form role="form" method="post">{% csrf_token %}
    <div class="form-group row">
        {% for f in form_obj %}
            {% if f.field.required %}
                <label class="col-sm-2 col-form-label"><b>{{ f.label }}</b></label>
            {% else %}
                <label class="col-sm-2 col-form-label">{{ f.label }}</label>
            {% endif %}
                <div class="col-sm-10" style="padding-top: 5px">
                    <div class="row">
                    {% if f.name in admin_class.filter_horizontal %}
                        <div class="col-md-2" >
                            {% get_m2m_obj_list admin_class f as m2m_obj_list %}
                             <select id="noselected_{{ f.name }}" multiple class="select-box">
                                 {% for obj in m2m_obj_list %}
                                     <option value="{{ obj.id }}" ondblclick="MoveToSelected(this,'selected_{{ f.name }}','noselected_{{ f.name }}')">{{ obj }}</option>
                                 {% endfor %}
                             </select>
                        </div>
                        <div class="col-md-1">
                            ===》<br>
                            《===
                        </div>
                        <div class="col-md-2">
                             <select id="selected_{{ f.name }}" multiple class="select-box" name="{{f.name}}" my_id="selectedalloption">
                                {% get_m2m_selected_list form_obj f as selected_list %}
                                 <!-- 上面是使用自定义标签获取已选择项数据-->
                                 <!-- 下面是经过测试,使用f的initial也能获取到,不需要再定义标签 -->
                                 {% for obj in f.initial %}
                                    <option value="{{ obj.id }}" ondblclick="MoveToSelected(this,'noselected_{{ f.name }}','selected_{{ f.name }}')">{{ obj }}</option>
                                 {% endfor %}
                             </select>
                        </div>
                    {% else %}
                            {{ f }}
                    {% endif %}
                    </div>
                </div>
        {% endfor %}
    </div>
    <div class="form-group row" style="float: right;margin-right: 100px">
        <div class="col-sm-10  pull-right">

            <button type="submit" class="btn btn-success pull-right">Save</button>
        </div>
    </div>
</form>
<script>
        function MoveToSelected(ele,target_id,self_id) {
            var opt_ele = '<option value="' + $(ele).val() +'"' + ' ondblclick=MoveToSelected(this,"' +self_id +'","' +target_id + '")>' + $(ele).text() + '</option>';
            console.log(opt_ele)
            $("#" + target_id).append(opt_ele);
            $(ele).remove()
        }

    </script>

然后在提交的时候,需要再对应选择的多选下拉框中的数据做全部选中状态,这样提交时才能带过去数据:<form role="form" method="post" οnsubmit="return SelectedAll();">,增加onsubmit

        function SelectedAll() {
            $("select[my_id='selectedalloption'] option").each(function () {
                $(this).prop("selected",true)
            });
            return true

        }

 有一个BUG,在前端使用f.initial遍历已选数据项时,提交后数据没有刷新,修改使用自定义标签

<form role="form" method="post" onsubmit="return SelectedAll();">{% csrf_token %}
    <div class="form-group row">
        {% for f in form_obj %}
            {% if f.field.required %}
                <label class="col-sm-2 col-form-label"><b>{{ f.label }}</b></label>
            {% else %}
                <label class="col-sm-2 col-form-label">{{ f.label }}</label>
            {% endif %}
                <div class="col-sm-10" style="padding-top: 5px">
                    <div class="row">
                    {% if f.name in admin_class.filter_horizontal %}
                        <div class="col-md-2" >
                            {% get_m2m_obj_list admin_class f form_obj as m2m_obj_list %}
                             <select id="noselected_{{ f.name }}" multiple class="select-box" name="{{ f.name }}">
                                 {% for obj in m2m_obj_list %}
                                     <option value="{{ obj.id }}" ondblclick="MoveToSelected(this,'selected_{{ f.name }}','noselected_{{ f.name }}')">{{ obj }}</option>
                                 {% endfor %}
                             </select>
                        </div>
                        <div class="col-md-1">
                            ===》<br>
                            《===
                        </div>
                        <div class="col-md-2">
                             <select my_id="selectedalloption" id="selected_{{ f.name }}" multiple class="select-box" name="{{ f.name }}">
                                {% get_m2m_selected_list form_obj f as selected_list %}
                                 <!-- 上面是使用自定义标签获取已选择项数据-->
                                 <!-- 下面是经过测试,使用f的initial也能获取到,不需要再定义标签 -->
                                 {% for obj in selected_list %}
                                    <option value="{{ obj.id }}" ondblclick="MoveToSelected(this,'noselected_{{ f.name }}','selected_{{ f.name }}')">{{ obj }}</option>
                                 {% endfor %}
                             </select>
                        </div>
                    {% else %}
                            {{ f }}
                    {% endif %}
                    </div>
                </div>
        {% endfor %}
    </div>
    <div class="form-group row" style="float: right;margin-right: 100px">
        <div class="col-sm-10  pull-right">

            <button type="submit" class="btn btn-success pull-right">Save</button>
        </div>
    </div>
</form>
@register.simple_tag
def get_m2m_obj_list(admin_class,f,form_obj):  # 获取没有被选择的所有项
    field_obj = getattr(admin_class.model,f.name)
    all_obj_list = field_obj.rel.model.objects.all()
    if field_obj.instance.id:
        selected_list = getattr(form_obj.instance,f.name).all()
    else: # 对于新增记录,没有id,直接返回所有
        return all_obj_list
    print('================================all=======')
    print(all_obj_list)
    print('=========================selected=======')
    print(selected_list)
    noselect_list = []
    for obj in all_obj_list:
        if obj not in selected_list:
            noselect_list.append(obj)
    print('=====没有选择的====',noselect_list)
    return noselect_list


@register.simple_tag
def get_m2m_selected_list(form_obj,f):    # 获取所有已选择的项
    selected_obj = getattr(form_obj.instance,f.name)
    print('标签,已选:',selected_obj.all())
    return selected_obj.all()

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

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

相关文章

MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作

什么是MaxEnt模型&#xff1f; MaxEnt模型的原理是什么&#xff1f;有哪些用途&#xff1f; MaxEnt运行需要哪些输入文件&#xff1f;注意那些事项&#xff1f; 融合R语言的MaxEnt模型的优势&#xff1f; 常用数据检索与R语言自动化下载及可视化方法 常用数据下载网站&…

第一章《初学者问题大集合》第7节:编写第一个Java程序

下载并安装好IDEA之后&#xff0c;就可以编写Java程序啦&#xff01;前文曾经讲过&#xff0c;Java程序最初的存在形式是Java源文件&#xff0c;经过编译之后又会产生字节码文件。当今时代&#xff0c;软件项目的规模越来越大&#xff0c;因此软件项目中会有多个Java源文件和字…

Android Gradle - AGP(Android Gradle Plugin)更新失败,你遇到了吗?

因为项目中有Java和Kt&#xff0c;同时也是组件化项目&#xff0c;所以配置方面一直存在一些问题&#xff08;项目可正常运行&#xff0c;只是影响开发效率&#xff09;&#xff0c;此处仅记录我在AndroidStudio中更新AGP&#xff08;Android Gradle Plugin,即Android 官方开发…

jmeter 使用

下载安装 去官网下载binary文件https://jmeter.apache.org/download_jmeter.cgi 解压后&#xff0c;进入解压目录的 /bin/ &#xff0c;通过 sh jmeter 命令来启动 Jmeter。 使用jmeter GUI创建test plan 创建线程组流程&#xff1a;测试计划–>右键–>添加–>线程…

threeJS与模型交互

效果预览 该场景是模拟两个楼层&#xff0c;当鼠标放到不同的楼层上时改变其透明度 blender中的模型如下图&#xff1a; 首先导入模型 import { FBXLoader } from three/examples/jsm/loaders/FBXLoader.js addfbx () {const loader new FBXLoader()loader.load(/models/…

算法:最长递增子序列

一、题目描述 给定一个长度为N的数组a0,a1,a2…,an-1&#xff0c;找出一个最长的单调递增子序列&#xff08;注&#xff1a;递增的意思是对于任意的i<j&#xff0c;都满足ai<aj&#xff0c;此外子序列的意思是不要求连续&#xff0c;顺序不乱即可&#xff09;。例如&…

K8s自动化集群环境搭建

文章目录一、环境规划1.1 集群类型1.2 安装方式二、环境搭建1、主机安装2、主机名分配3、时钟同步4. 禁用firewalld、selinux、postfix5. 禁用swap分区6. 开启IP转发&#xff0c;和修改内核信息7. 配置IPVS功能8. ssh免密认证三、安装docker1、更换阿里云镜像仓库2、安装docker…

【前端】HTTP —— HTTP 协议中的细节(超详细!!)

JavaEE传送门JavaEE 【前端】JavaScript —— JS的基本语法之数组, 函数… 【前端】JavaScript —— WebAPI 目录HTTP 协议抓包工具 fiddler协议格式RequestResponseHTTP 协议中的细节认识 URLURL 基本格式URL encode/ decode认识 "方法" methodGETPOSTGET 和 POST…

感叹之余随手记—他山之石,可以攻玉

如上是开源webRTC项目的一个OC代码文件&#xff0c;注意到文件名是mm后缀了吗&#xff1f; 是的&#xff0c;它是一个OC特性之OC跟C/C代码混编&#xff0c;上面的代码就C runtime跟OC runtime的string对象的互相转化。 开源成就了很多人很多事&#xff01; 开源提升了我们的工作…

MySQL高级学习笔记(二)

文章目录MySQL高级学习笔记(二)1.Mysql的体系结构概览2. 存储引擎2.1 存储引擎概述2.2 各种存储引擎特性2.2.1 InnoDB2.2.2 MyISAM2.2.3 MEMORY2.2.4 MERGE2.3 存储引擎的选择3. 优化SQL步骤3.1 查看SQL执行频率3.2 定位低效率执行SQL3.3 explain分析执行计划3.3.1 环境准备3.3…

【JavaSE】内部类介绍与总结

文章目录内部类的概念静态内部类实例内部类局部内部类匿名内部类内部类的概念 什么是内部类呢&#xff1f;在一个类里面定义了另一个类&#xff0c;我们就把前者称为外部类&#xff0c;后者称为内部类。 静态内部类 内部类也是有分类的&#xff0c;我们先来看看静态的内部类…

开源的滚滚浪潮:近年来开源多样化的几大亮点

导读目前参与进开源社区的人群仍然缺乏多样性&#xff0c;但是好的一面是&#xff0c;许多人、项目和社区正在努力改善这一现状。我从开源社区在2015年以来为提高多样性作出的努力中收集了几大亮点。Outreachy 发展多样性的实习项目 Outreachy 作为软件自由管理局的成员项目之…

7种方式企业内部资料共享,你pick谁?

企业内部资料共享&#xff0c;很多公司也还停留在用微信和QQ分享文件&#xff0c;但小编认为通过IM方式&#xff0c;只能说“发送”文件而已&#xff0c;并没有达到“共享”的需求。 试想一下这几个场景就能明白&#xff1a; 内部材料收集&#xff0c;是一份份地通过微信发送给…

OPENFLOW协议协议分析实践

一、基本要求 1.搭建下图所示拓扑&#xff0c;完成相关 IP 配置&#xff0c;并实现主机与主机之间的 IP 通信。用抓包软件获取控制器与交换机之间的通信数据。 2.查看抓包结果&#xff0c;分析OpenFlow协议中交换机与控制器的消息交互过程&#xff0c;画出相关交互图或流程图。…

【后端】HTTP4

回顾一下之前学习的内容 通过之前的学习&#xff0c;我们大致了解了HTTP请求响应的报文格式 HTTP请求 &#xff08;1&#xff09;首行&#xff08;方法 URL 版本号&#xff09; &#xff08;2&#xff09;请求头 header &#xff08;3&#xff09;空行 &#xff08;4&a…

计算机网络(第六弹) --- 与 HTTP 有关的八个问题

当我们用浏览器打开一个网页时基本上都是基于 HTTP 协议来进行传输的, 其实用 APP 来打开一个界面看到的 APP 中的内容大概率也是基于 HTTP 协议传输的, 因此 HTTP 对于网络而言的重要性不言而喻!   HTTP 这个协议在传输层主要是基于 TCP 来实现的, TCP 是传输字节流的协议, 只…

客户生命周期管理的五个最佳实践

每个优秀的客户服务人员都知道&#xff0c;业务不仅仅是完成一次性交易。优秀的企业与客户建立互惠互利的关系&#xff0c;相当于提高了客户的终身价值。换句话说&#xff0c;他们确保客户长时间留下来。本文将讨论客户生命周期管理的一些最佳实践。 1、与潜在客户和客户进行个…

业务数据分析-Excel必须掌握的7个操作技巧(二)

Excel必须掌握的7个操作技巧1、定位2、选择性粘贴3、快速填充4、查找与替换5、分列与合并6、去除重复项7、日期格式规范1、定位 如何快速定位到不连续的空值&#xff0c;填充为0 1.在任意空单元格里复制0 2.选中数据区域CtrlA 3.CtrlG 4.选择【定位条件】 5.选择【空值】 6.Ct…

如何使用Docker安装Kibana

&#xff08;一&#xff09;、概述 Kibana是一款开源的数据分析和可视化Web平台&#xff0c;用于对 Elasticsearch 索引中的数据进行搜索、查看、修改、添加和删除操作。 &#xff08;二&#xff09;、安装 1、Docker环境 视频教程&#xff1a;https://www.bilibili.com/vi…

ifconfig 查看 etcd 使用的 IP 是否存在

在该节点上 ping 其他节点 IP&#xff0c;测试是否 ping 通。 如果 ping 不通&#xff0c;执行步骤&#xff08;1&#xff09;&#xff08;2&#xff09;&#xff0c;检查该节点网络、IP 配置、防火墙配置等。 如果 ping 通&#xff0c;执行步骤&#xff08;3&#xff09;确认…