• day19 Dgango进阶 路由系统及 ORM 详解


    完成一个完整的网页服务,需要有以下:

    再次回顾一下Django 的完成开发流程:

    一些值的获取:

    对于性别,为互斥属性:

    爱好则为多选:

    需要使用新的方法 getlist 来获取多个爱好:

    单选下拉框选择获取:

    多选下拉框也需要用到getlist 

     对于上传文件的设置:

    1 首先form 表单要设置特殊属性:

       

    2 文件上传使用新的方法:

     

      使用chunks 来一点一点获取数据:

    上传文件到指定目录:

    总结一下常用的方法:

    然后来实践一下,把上面的全部实现一下:

    views:

    from django.shortcuts import render,redirect,HttpResponse
    
    # Create your views here.
    def user(request):
        print('user')
        if request.method == 'GET':
            return render(request,'user.html')
        elif request.method == 'POST':
            #用户名
            u = request.POST.get('user')
            #密码
            p = request.POST.get('pwd')
            #性别
            g = request.POST.get('gender')
            #城市
            c = request.POST.get('city')
            #爱好
            f = request.POST.getlist('favor')
            print(u,p,g,c,f)
            #文件是一个对象,可以查看对象,大小等
            f_obj = request.FILES.get('up_head_img')
            #获取文件名
            f_name = f_obj.name
            f_size = f_obj.size
            print(f_name,f_size)
            #真正接收并存到本地
            import os
            file_path = os.path.join('upload',f_obj.name)
            block_size = 0
            with open(file_path,mode='wb') as f:
                for block in f_obj.chunks():
                    #用这个来获取的当前已经上传了多少,可以给用户返回
                    block_size += len(block)
                    print(block_size)
                    f.write(block)
            print(f_obj.name,'传完了')
            return HttpResponse('200')
    

    urls:

     html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/user/" method="POST" enctype="multipart/form-data">
            <div class="text">
                <label>用户名</label>
                <input type="text" name="user"/>
                <label>密码</label>
                <input type="password" name="pwd"/>
            </div>
            <div class="chose">
                <div>
                    <label>性别</label>
                    <input type="radio" name="gender" value="1"/>男
                    <input type="radio" name="gender" value="2"/>女
                </div>
                <div>
                    <label>城市</label>
                    <select name="city">
                        <option value="sh">上海</option>
                        <option value="bj">北京</option>
                        <option value="tj">天津</option>
                        <option value="sjz">石家庄</option>
                    </select>
                </div>
                <div>
                    <label>爱好</label>
                    <input type="checkbox" name="favor" value="1"/>骑行
                    <input type="checkbox" name="favor" value="2"/>旅游
                    <input type="checkbox" name="favor" value="3"/>音乐
                    <input type="checkbox" name="favor" value="4"/>电影
                    <input type="checkbox" name="favor" value="5"/>把妹
                    <input type="checkbox" name="favor" value="6"/>吃吃吃
                </div>
            </div>
            <div class="upload">
                <label>上传头像</label>
                <input type="file" name="up_head_img"/>
            </div>
            <input type="submit" value="提交所有数据"/>
        </form>
    </body>
    </html>
    

    效果:

    Django 有两种方式:

    1 FBV

       function  base view

       function函数处理的方式

    2 CBV

       class base view

       class类处理的方式

    写一个类处理的方式:

    1 先导入View 模块

    2 定义类及里面的属性

     

    3 定义url:

    4 html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div>
            <form action="/home/" method="POST">
            <h1>测试Class 处理方式 CBV</h1>
            <input type="submit" value="测试提交方法"/>
            </form>
        </div>
    </body>
    </html>
    

    5 测试:

     

      

    在这里我们可以实现一个类似装饰器的功能,就是在类里的方法执行前或后添加一些其他功能:

    使用dispatch 函数:

    from django.views import View
    class Home(View):
        def dispatch(self, request, *args, **kwargs):
            #调用父类中的
            print('访问前要执行的')
            result = super(Home,self).dispatch(request,*args,**kwargs)
            print('访问后要执行的')
            return result
        
        def get(self,request):
            print('使用方法:', request.method)
            return render(request,'home.html')
        def post(self,request):
            print('使用方法:',request.method)
            return render(request, 'home.html')
    

    测试:

    以上为常用的方法。

    下面学习下模板语言:

    1 在html 中如何循环得道的字典数据呢?

       实践:

      views: 

    USER_DICT = {
        'k1': 'root1',
        'k2': 'root2',
        'k3': 'root3',
        'k4': 'root4',
        'k5': 'root5',
    }
    
    def moban(request):
    
        return render(request,'moban.html',{'USER_DICT':USER_DICT})

      html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div>
            <span>测试for 循环 只循环key</span>
            <ul>
                {% for k in USER_DICT.keys %}
                <li>{{ k }}</li>
                {% endfor %}
            </ul>
        </div>
        <div>
            <span>测试for 循环 只循环value</span>
            <ul>
                {% for v in USER_DICT.values %}
                <li>{{ v }}</li>
                {% endfor %}
            </ul>
        </div>
        <div>
            <span>测试for 循环 全部循环</span>
            <ul>
                <li>k -- v</li>
                {% for k,v in USER_DICT.items %}
                <li>{{ k }} -- {{ v }}</li>
                {% endfor %}
            </ul>
        </div>
    </body>
    </html>

      urls:

    from user import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^user/', views.user),
        url(r'^home/', views.Home.as_view()),
        url(r'^moban/', views.moban),
    ]

      效果:

    下面实现一个稍微复杂一点的:

    1 列出字典的k及value里的一个值

      views:

    USER_INFO = {
        '1': {'name':'shenyang','age':25,'mail':'123@qq.com'},
        '2': {'name':'wang','age':18,'mail':'456@qq.com'},
        '3': {'name':'xiaoming','age':19,'mail':'789@qq.com'},
        '4': {'name':'xiaohua','age':11,'mail':'101112@qq.com'},
    }
    
    def list(request):
        return render(request,'list.html',{'USER_INFO':USER_INFO})

      urls:

    url(r'^list/', views.list),

      html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>用户列表</h1>
        <div>
            <ul>
                {% for k,v in USER_INFO.items %}
                    <li><a target="_blank" href="/detail-{{ k }}.html">{{ k }} -- {{ v.name }}</a></li>
                {% endfor %}
            </ul>
        </div>
    </body>
    </html>

      效果:

    2 实现通过点击连接,进入新的网页并显示value里的所有值

       用到的点有:

             1 url的正则匹配

             2 通过url的数据定位某一个数据

       views:

    USER_INFO = {
        '1': {'name':'shenyang','age':25,'mail':'123@qq.com'},
        '2': {'name':'wang','age':18,'mail':'456@qq.com'},
        '3': {'name':'xiaoming','age':19,'mail':'789@qq.com'},
        '4': {'name':'xiaohua','age':11,'mail':'101112@qq.com'},
    }
    
    def list(request):
        return render(request,'list.html',{'USER_INFO':USER_INFO})
    
    def detail(request,nid):
        detail_info = USER_INFO[nid]
        return render(request,'details.html',{'detail_info':detail_info})
    

    urls:

    from user import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^user/', views.user),
        url(r'^home/', views.Home.as_view()),
        url(r'^moban/', views.moban),
        url(r'^list/', views.list),
        url(r'^detail-(?P<nid>d+).html', views.detail),
    ]
    

    html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h2>详细信息</h2>
        <div>
            <h6>用户名:{{ detail_info.name }}</h6>
            <h6>年龄:{{ detail_info.age }}</h6>
            <h6>邮箱:{{ detail_info.mail }}</h6>
        </div>
    </body>
    </html>
    

    效果:

    我们不仅可以通过url 获取一个数据,还能获取多个数据:

    匹配规则:

      匹配类似于 detail-1-2.html 这种两个数字的:

     

     函数获取数据:

      

    但是这样有一个不好的就是当url中这两个数字换了以后代码里的函数获取的数据也就不正确了,所以需要给匹配到的指定一个变量,这样就不再需要关心顺序了:

    函数获取数据:

    不管顺序,直接获取:

    nid 就是nid  uid 就是uid

    这里很重要,总结一下:

    路由系统,URL的三种方式:

    1 直接匹配,不需要获取数据:

    2 通过正则匹配,但是在函数获取数据时必须注意前后顺序:

    3 通过正则匹配到后不需要关心顺序,但是url中需要指定变量名称:

    url不仅可以匹配数字,还可以通过各种匹配,函数还可以以字典方式和列表方式获取数据:

    例如函数中以字典方式获取数据:

    views:

    def dic_test(request,**kwargs):
        print('This dic is: ',kwargs)
        nid = kwargs['nid']
        uid = kwargs['uid']
        all = 'This is ' + nid + ' and ' + uid
        return HttpResponse(all)
    

    urls:

    url(r'^dic_test-(?P<nid>d+)-(?P<uid>d+).html', views.dic_test),
    

    html:

    效果:

    url 地址还可以给一个变量,用于在html 模板中跳转到指定变量的地址中:

     当然如果想获取绝对的url地址,使用:

     

    因为在模板渲染的时候响应函数已经把所有的request 传入,所以想获取哪个数据,只要request中有,就一定能获取到,并渲染到模板中

    另一种方式自己跳转到自定义页面:

    需要用到 reverse 模块:

    例如:

    把name 为 i2 的url 自定义一个url 通过列表形式转换为自定义url

    urls:

    viwes:

    from django.urls import reverse
    def custom_url_i2(request,*args,**kwargs):
        print(request.path_info)
        url2 = reverse('i2',args=(8,12))
        print(url2)
        return HttpResponse(url2)
    

    效果:

    把name 为 i3 的url 自定义一个url 通过字典形式转换为自定义url

    urls:

    viwes:

    def custom_url_i3(request,*args,**kwargs):
        print(request.path_info)
        url3 = reverse('i3',kwargs={'uid':88,'nid':66})
        print(url3)
        return HttpResponse(url3)
    

    效果:

     总结一下:

    当然上面这些是只有Django 才有的方式

    路由系统中另一个强大的功能叫做路由分发系统:

    详细来说就是通过指定一个url 到另一个url路由文件就可以实现多个项目与主路由的松耦合,这样开发者可以自己修改自己的项目的url地址而不会影响到其他项目:

    实现:

    项目主urls:

    user模块urls:

    user viwes:

    host模块urls:

    host viwes:

    效果:

     路由系统暂时到此。

    开始ORM:

    ORM分为两类:

    1  DBfirst      先创建数据库表结构  根据表结构自动生成类, 以后修改这个类就可以修改数据库
    2  Codefirst   先写代码,写好要创建的数据库的表的类,然后自动生成表结构

     Django中的为Codefirst

    使用Django 创建一个用户表:

    1 写类

    from django.db import models
    # Create your models here.
    class User_info(models.Model):
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)

    2 修改setting 添加app

    3 执行命令生成表

    python manage.py makemigrations
    python manage.py migrate 

    4 检查

     

    Django 创建表的时候表名为:

    app名_表的类名

     

    这里我们在没有做修改之前默认用的是SQLite数据库,使用mysql 数据库:

    完整使用mysql 数据库的步骤:

    1 修改项目的__init__.py 添加pymysql

    2 修改setting 使用mysql 连接

    3 在app中写一个类:

    4 修改setting 注册app

    5 执行命令生成表

    manage.py makemigrations
    manage.py migrate
    

    6 查看表:

    配置完后学一下增删改查:

    1 增加:

       a方式:

          

       b方式:

         

     以字典形式增加数据:

         

     2 查:

      查所有:

       

        查到一个QuerySet 的格式的数据,直接理解为是一个列表。
        列表中每一个元素都是一个对象

     过滤(where)查询:

       

       这里也是一个列表,因为用户名称等于root的可能有多个,所以要通过列表循环获取数据

     组合查询(and条件):

       

       虽然查到了一个但是查到的结果类型还是一个列表,所以还要循环

    删除:

      过滤删除:

      

      全部删除:

       .all().delete()

    更新:

      全部更新:

      

      过滤更新:

      

    实践一下:

    from host_manage import models
    def orm(request):
        # 增加
        models.User_info.objects.create(username='root',password='123')
        # 查看
        result = models.User_info.objects.all()
        for row in result:
            print(row.id,row.username,row.password)
        #删除
        models.User_info.objects.filter(username='alex').delete()
        #更新
        models.User_info.objects.filter(id=2).update(password='66666')
        return HttpResponse('orm')
    

     实现查询的时候只拿取第一个,并返回一个对象:

      first() 方法:

     

      这样查找之后就会取过滤后的第一个对象,这里可以判断如果对象存在就说明有数据,如果为None 则数据不存在

      也可以用下面的计数查询,如果大于0说明有数据,但是不能获取到多个信息,不常用:

      

      还有一种获取对象的方式,但是不推荐,需要配合try来使用:

     

    查看真实的sql 语句,就是在操作对象时执行的sql:

     写一个列出和添加用户的小功能:

    1 views

    from user import models
    def user_info(request):
        if request.method == 'GET':
            user_list = models.UserInfo.objects.all()
            print(user_list)
            return render(request,'user_info.html',{'user_list':user_list})
        elif request.method == 'POST':
            u = request.POST.get('user')
            p = request.POST.get('pwd')
            print(u,p)
            models.UserInfo.objects.create(username=u,password=p)
            return redirect('/user/user_info/')

    2 models

    from django.db import models
    
    # Create your models here.
    class  UserInfo(models.Model):
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)

    3 urls

    from django.conf.urls import url
    from user import views
    urlpatterns = [
        url(r'^login/',views.login),
        url(r'^list/',views.list),
        url(r'^user_info/',views.user_info),
    ]

    4 html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/user/user_info/" method="POST">
    
            <h2>用户列表</h2>
            <ul>
                {% for i in user_list %}
                <li>{{ i.username }}</li>
                {% endfor %}
            </ul>
            <input type="text" name="user" placeholder="用户名" /></div>
            <div><input type="password" name="pwd" placeholder="密码" /></div>
            <input type="submit" value="添加用户"/>
        </form>
    </body>
    </html>

    5 效果

     

    继续添加点击用户名可以查看详细信息功能:

     使用url 的正则匹配形式:

    1 views

    from user import models
    def user_info(request):
        if request.method == 'GET':
            user_list = models.UserInfo.objects.all()
            print(user_list)
            return render(request,'user_info.html',{'user_list':user_list})
        elif request.method == 'POST':
            u = request.POST.get('user')
            p = request.POST.get('pwd')
            print(u,p)
            models.UserInfo.objects.create(username=u,password=p)
            return redirect('/user/user_info/')
    
    def user_detail(request,nid):
        print(nid)
        user_info = models.UserInfo.objects.filter(id=nid).first()
        return render(request,'userdetail.html',{'user_info':user_info})

    2 urls

    from django.conf.urls import url
    from user import views
    urlpatterns = [
        url(r'^login/',views.login),
        url(r'^list/',views.list),
        url(r'^user_info/',views.user_info),
        url(r'^userdetail-(?P<nid>d+).html/',views.user_detail),
    ]

    3 html

     userinfo

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/user/user_info/" method="POST">
    
            <h2>用户列表</h2>
            <ul>
                {% for i in user_list %}
                <li>{{ i.username }}    <a href="/user/userdetail-{{ i.id }}.html">详细</a></li>
                {% endfor %}
            </ul>
            <input type="text" name="user" placeholder="用户名" /></div>
            <div><input type="password" name="pwd" placeholder="密码" /></div>
            <input type="submit" value="添加用户"/>
        </form>
    </body>
    </html>

    userdetail

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            <li>{{ user_info.username }} -- {{ user_info.password }}</li>
        </ul>
    </body>
    </html>

    4 效果

    最后添加删除和编辑功能:

    1 删除:

       最简单,根据id直接操作数据库然后返回到用户列表页即可

    2 修改:

       返回指定id的数据到input 框,当修改后根据id提交

    views:

    from user import models
    def user_info(request):
        if request.method == 'GET':
            user_list = models.UserInfo.objects.all()
            print(user_list)
            return render(request,'user_info.html',{'user_list':user_list})
        elif request.method == 'POST':
            u = request.POST.get('user')
            p = request.POST.get('pwd')
            print(u,p)
            models.UserInfo.objects.create(username=u,password=p)
            return redirect('/user/user_info/')
    
    def user_detail(request,nid):
        print(nid)
        user_info = models.UserInfo.objects.filter(id=nid).first()
        return render(request,'userdetail.html',{'user_info':user_info})
    
    def user_del(request,nid):
        print(nid)
        models.UserInfo.objects.filter(id=nid).delete()
        return redirect('/user/user_info/')
    
    def user_edit(request,nid):
        print(nid)
        if request.method =='GET':
            user = models.UserInfo.objects.filter(id=nid).first()
            return render(request,'useredit.html',{'user':user})
        elif request.method == 'POST':
            u = request.POST.get('username')
            p = request.POST.get('password')
            print(u,p)
            models.UserInfo.objects.filter(id=nid).update(username=u,password=p)
            return redirect('/user/user_info/')

    urls:

    from django.conf.urls import url
    from user import views
    urlpatterns = [
        url(r'^login/',views.login),
        url(r'^list/',views.list),
        url(r'^user_info/',views.user_info),
        url(r'^userdetail-(?P<nid>d+).html/',views.user_detail),
        url(r'^userdel-(?P<nid>d+).html/',views.user_del),
        url(r'^useredit-(?P<nid>d+).html/',views.user_edit),
    ]

    html:

    userinfo:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/user/user_info/" method="POST">
    
            <h2>用户列表</h2>
            <ul>
                {% for i in user_list %}
                <li>{{ i.username }}    <a href="/user/userdetail-{{ i.id }}.html">详细|</a><a href="/user/userdel-{{ i.id }}.html">删除|</a><a href="/user/useredit-{{ i.id }}.html">编辑</a></li>
                {% endfor %}
            </ul>
            <input type="text" name="user" placeholder="用户名" /></div>
            <div><input type="password" name="pwd" placeholder="密码" /></div>
            <input type="submit" value="添加用户"/>
        </form>
    </body>
    </html> 

    useredit:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h2>修改用户信息</h2>
        <form action="/user/useredit-{{ user.id }}.html/" method="POST">
            <input type="text" name="nid" value="{{ user.id }}" style="display: none"/>
            <input type="text" name="username" value="{{ user.username }}"/>
            <input type="text" name="password" value="{{ user.password }}"/>
            <input type="submit" value="提交修改"/>
        </form>
    </body>
    </html>
    

    效果:

    基本的增删改查就到这里,下面说一下增加列和删除列:

    通过Django 的ORM 操作数据库其实很简单:

    增加列:

      1直接在class中增加一个属性就行

      

    2 执行命令,生成表结构:

      

    删除列:

      1 直接注释掉需要删除的列 

      2 执行命令删除

      

     Django 中的ORM 有很多的数据类型,但是其本质也就是数据库那几种类型,只是Django 会帮你做一层验证:

     

     

    数据表的一些其他操作:

     

     指定列名:

    建立索引:

    建立唯一索引:

    注册时间,创建时间,可是使用这个:

     创建的时候,就是第一次生成的时间,自动生成
     更新的时候会自动更新时间, 但是需要注意:

     

    下面这种才会更新:

     

    创建一个choices 类型的表:

    Django 的admin 会自动当作选项:

    存入数据库的还是数字,避免了连表查询

     

    总结一下字段的参数:

    Django admin 显示字段中文

     

    自定义帮助信息,在旁边坐一个小的提示:

    admin 的其他一些方法:

     
     
    开始学习连表查询:
     
    建立关联键:
    不加关联哪个表的话默认也是关联主键

    实际上在数据库中会生成 user_group_id 这个表 

    通过这个关联键 获取数据:

    创建一个值: 

     

    直接写入本地数据库而不是跨表写入

    态的下拉框:

     实践:

    添加一个在创建用户的时候指定组的功能,下拉框中的数据来自另一个表的数据,存储的时候直接存储到本表。

    先实现展示的功能:

    models:

    创建关联的外键:

    from django.db import models
    
    # Create your models here.
    class UserGroup(models.Model):
        uid = models.AutoField(primary_key=True)
        caption = models.CharField(max_length=32,unique=True)
        ctime = models.DateTimeField(auto_now_add=True,null=True)
        uptime = models.DateTimeField(auto_now=True,null=True)
    
    class  UserInfo(models.Model):
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
        user_group = models.ForeignKey('UserGroup',to_field='uid')
    

    插入几条数据,重新刷新一下数据库,发现 userinfo表里增加了一个 user_group_uid 的列,而不是user_group,这是因为外键关联的是一个对象,而不是真正的列

     views:

    处理数据,在获取组的时候使用外键的方式:

    from user import models
    def user_info(request):
        if request.method == 'GET':
            user_list = models.UserInfo.objects.all()
            group_list = models.UserGroup.objects.all()
            print(user_list)
            return render(request,'user_info.html',{'user_list':user_list,'group_list':group_list})
        elif request.method == 'POST':
            u = request.POST.get('user')
            p = request.POST.get('pwd')
            g = request.POST.get('group')
            print(u,p,g)
            models.UserInfo.objects.create(username=u,password=p,user_group_id=g)
            return redirect('/user/user_info/')
    
    def user_detail(request,nid):
        print(nid)
        user_info = models.UserInfo.objects.filter(id=nid).first()
        return render(request,'userdetail.html',{'user_info':user_info}) 

    html:

    info:

    以点的方式继续操作另一张表

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/user/user_info/" method="POST">
    
            <h2>用户列表</h2>
            <ul>
                <li> 用户名 -- 组</li>
                {% for i in user_list %}
                <li>{{ i.username }}  --  {{ i.user_group.caption }}  <a href="/user/userdetail-{{ i.id }}.html">详细|</a><a href="/user/userdel-{{ i.id }}.html">删除|</a><a href="/user/useredit-{{ i.id }}.html">编辑</a></li>
                {% endfor %}
            </ul>
            <input type="text" name="user" placeholder="用户名" /></div>
            <div><input type="password" name="pwd" placeholder="密码" /></div>
            <div><select name="group" >
                {% for g in group_list %}
                <option value="{{ g.uid }}">{{ g.caption }}</option>
                {% endfor %}
                </select>
            </div>
            <input type="submit" value="添加用户"/>
        </form>
    </body>
    </html>

    detail:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            <li>   用户名    --    密码      --      组</li>
            <li>{{ user_info.username }} -- {{ user_info.password }} -- {{ user_info.user_group.caption }}</li>
        </ul>
    </body>
    </html>
    

    效果:

     

  • 相关阅读:
    inode满处理
    power shell 脚本了解
    免密脚本带端口
    linux文件 特殊权限的使用
    linux批量配置ip
    编译安装常用包+阿里镜像源-常用资源-系统-下载-科莱软件下载-docker仓库包-安全圈-杏雨梨云-图形界面安装-docker私有双仓库-阿里源报错处理-centos7目录大小
    expect免互交 常用编辑文本
    vim 插件 -- taglist
    vim 插件 -- ctags
    vim 插件 -- omnicppcomplete
  • 原文地址:https://www.cnblogs.com/yangever/p/6188023.html
Copyright © 2020-2023  润新知