• 代码发布项目(三)——python操作git、代码发布流程(服务器管理、项目管理)


    一、python如何操作git

    如果你想用python代码操作git需要下载一个模块

    安装

    pip install gitpython

    基本使用

    # 从远处仓库下载代码到本地
    import os
    from git.repo import Repo
    
    # 创建本地存储地址,没有会自动创建文件
    download_path = os.path.join('jason','NB')
    # 从远程仓库下载代码
    Repo.clone_from('https://github.com/DominicJi/TeachTest.git',to_path=download_path,branch='master')

    常用方法大全

    # ############## 2. pull最新代码 ##############
    import os
    from git.repo import Repo
     
    local_path = os.path.join('jason', 'NB')
    repo = Repo(local_path)
    repo.git.pull()
    
    # ############## 3. 获取所有分支 ##############
    import os
    from git.repo import Repo
     
    local_path = os.path.join('jason', 'NB')
    repo = Repo(local_path)
     
    branches = repo.remote().refs
    for item in branches:
        print(item.remote_head)
        
    # ############## 4. 获取所有版本 ##############
    import os
    from git.repo import Repo
     
    local_path = os.path.join('jason', 'NB')
    repo = Repo(local_path)
     
    for tag in repo.tags:
        print(tag.name)
    
    # ############## 5. 获取所有commit ##############
    import os
    from git.repo import Repo
     
    local_path = os.path.join('jason', 'NB')
    repo = Repo(local_path)
     
    # 将所有提交记录结果格式成json格式字符串 方便后续反序列化操作
    commit_log = repo.git.log('--pretty={"commit":"%h","author":"%an","summary":"%s","date":"%cd"}', max_count=50,
                              date='format:%Y-%m-%d %H:%M')
    log_list = commit_log.split("
    ")
    real_log_list = [eval(item) for item in log_list]
    print(real_log_list)
     
    # ############## 6. 切换分支 ##############
    import os
    from git.repo import Repo
     
    local_path = os.path.join('jason', 'NB')
    repo = Repo(local_path)
     
    before = repo.git.branch()
    print(before)
    repo.git.checkout('master')
    after = repo.git.branch()
    print(after)
    repo.git.reset('--hard', '854ead2e82dc73b634cbd5afcf1414f5b30e94a8')
     
    # ############## 7. 打包代码 ##############
    with open(os.path.join('jason', 'NB.tar'), 'wb') as fp:
        repo.archive(fp)

    把上面功能封装成类

    import os
    from git.repo import Repo
    from git.repo.fun import is_git_dir
    
    
    class GitRepository(object):
        """
        git仓库管理
        """
    
        def __init__(self, local_path, repo_url, branch='master'):
            self.local_path = local_path
            self.repo_url = repo_url
            self.repo = None
            self.initial(repo_url, branch)
    
        def initial(self, repo_url, branch):
            """
            初始化git仓库
            :param repo_url:
            :param branch:
            :return:
            """
            if not os.path.exists(self.local_path):
                os.makedirs(self.local_path)
    
            git_local_path = os.path.join(self.local_path, '.git')
            if not is_git_dir(git_local_path):
                self.repo = Repo.clone_from(repo_url, to_path=self.local_path, branch=branch)
            else:
                self.repo = Repo(self.local_path)
    
        def pull(self):
            """
            从线上拉最新代码
            :return:
            """
            self.repo.git.pull()
    
        def branches(self):
            """
            获取所有分支
            :return:
            """
            branches = self.repo.remote().refs
            return [item.remote_head for item in branches if item.remote_head not in ['HEAD', ]]
    
        def commits(self):
            """
            获取所有提交记录
            :return:
            """
            commit_log = self.repo.git.log('--pretty={"commit":"%h","author":"%an","summary":"%s","date":"%cd"}',
                                           max_count=50,
                                           date='format:%Y-%m-%d %H:%M')
            log_list = commit_log.split("
    ")
            return [eval(item) for item in log_list]
    
        def tags(self):
            """
            获取所有tag
            :return:
            """
            return [tag.name for tag in self.repo.tags]
    
        def change_to_branch(self, branch):
            """
            切换分值
            :param branch:
            :return:
            """
            self.repo.git.checkout(branch)
    
        def change_to_commit(self, branch, commit):
            """
            切换commit
            :param branch:
            :param commit:
            :return:
            """
            self.change_to_branch(branch=branch)
            self.repo.git.reset('--hard', commit)
    
        def change_to_tag(self, tag):
            """
            切换tag
            :param tag:
            :return:
            """
            self.repo.git.checkout(tag)
    
    
    if __name__ == '__main__':
        local_path = os.path.join('codes', 'luffycity')
        repo = GitRepository(local_path,remote_path)
        branch_list = repo.branches()
        print(branch_list)
        repo.change_to_branch('dev')
        repo.pull()

    二、服务器管理代码

    1.创建服务器表

    class Server(models.Model):
        """
        服务器表
        """
        hostname = models.CharField(max_length=32,verbose_name='主机名')

    额外补充:

    1.每一个应用都可以有自己的模版文件夹、静态文件夹、urls.py、还可以将views.py变成文件夹的形式,里面根据业务逻辑的不同再拆封成不同的py文件

    2.django默认全局语言环境是英文的,但是它内部其实支持多国语言,你可以修改语言环境

    # 配置文件中修改
    LANGUAGE_CODE = 'zh-hans'

    3.针对删除功能,以前的逻辑:后端直接删除对应的数据,然后重定向到展示页

    当数据特别多,并且涉及到分页的情况,我需要删除第99页的某一条数据,如果按照之前的方式则会跳到第一页

    较为完整的删除功能应该做到

    • 二次确认

    • DOM操作实现删除效果,前端删除

    2.服务器管理的增删改查

    创建好表之后,创建服务器管理展示页面。

    服务器查询:(展示所有服务器)

    def server_list(request):
        server_list=models.Server.objects.all()
        return render(request,'server_list.html',locals())
    #页面展示服务器id和hostname
    {% for server in server_list %}
              <tr>
              <td>{{ server.id }}</td>
              <td>{{ server.hostname }}</td>
              </tr>
     {% endfor %}

    服务器增加

    使用modelform筛选

    def server_add(request):
        #生成modelform对象
        form_obj=ServerModelForm()  #form组件还有渲染的功能,传递form对象给前端if request.method == 'POST':
            #校验数据
            form_obj=ServerModelForm(data=request.POST)  #form.html页面提交的数据
            if form_obj.is_valid():
                #合法保存数据
                form_obj.save()
                return redirect('server_list')
    
        return render(request,'form.html',locals())  #form_obj传递到form.html

    modelform的讲解文章:https://www.cnblogs.com/zhufanyu/p/11953623.html

    views.py

    def server_add(request):
        #生成modelform对象
        form_obj=ServerModelForm()  #form组件还有渲染的功能,传递form组件给前端
        print(form_obj)
        if request.method == 'POST':
            #校验数据
            form_obj=ServerModelForm(data=request.POST)  #form.html页面提交的数据
            if form_obj.is_valid():
                #合法保存数据
                form_obj.save()
                return redirect('server_list')
    
        return render(request,'form.html',locals())  #form_obj传递到form.html

    服务器编辑

    views.py

    def server_edit(request,edit_id):
        #根据edit_id查询出服务器对象
        edit_obj=models.Server.objects.filter(id=edit_id).first()
        #modelform中的instance可以用于初始化页面
        # 由于编辑页面跟添加页面长得其实是一样的 无外乎有没有默认数据  所以编辑和添加公用一个页面
        form_obj = ServerModelForm(instance=edit_obj)
        if request.method == 'POST':
            form_obj = ServerModelForm(data=request.POST,instance=edit_obj)  #用于更新
            if form_obj.is_valid(): #数据校验
                form_obj.save()
                return redirect('server_list')
    
        return render(request,'form.html',locals())

    服务器删除

    views.py

    def server_delete(request,delete_id):
        models.Server.objects.filter(id=delete_id).delete()  #数据库删除
        return HttpResponse({'status':True})

    server_list.html

    <a onclick="removeData(this,{{ server.id }})">删除</a>
    
    {% block js %}
      <script>
        function removeData(ths,rid) {
                // 二次确认
                var res = confirm('你确定要删除吗?');
                // 返回值是布尔值
                if(res){
                    // 朝后端发送删除数据的请求
                    $.ajax({
                        url:'/server/delete/' + rid + '/',
                        type:'get',
                        dataType:'JSON',
                        success:function (args) {
                            if(args.status){
                                // 前端DOM操作删除对应的标签
                                // 找到当前删除按钮所在的一行表格标签 删除即可
                                $(ths).parent().parent().remove();
                            }
                        }
                    })
                }
            }
      </script>
    {% endblock %}

    三、项目管理代码

    1.创建项目管理表

    class Project(models.Model):
        """
        项目表
        """
        title = models.CharField(max_length=30,verbose_name='项目名')
        repo=models.CharField(max_length=30,verbose_name='代码仓库地址')
        env_choice=(
            ('prod','正式'),  #prod是放在数据库的,正式是展示在前端的
            ('test','测试')
        )
        env = models.CharField(max_length=16,verbose_name='项目环境',choices=env_choice,default='test')
        path=models.CharField(max_length=255,verbose_name='线上项目地址',default='data/tmp')
        #项目与服务器的关系表
        servers=models.ManyToManyField(to='Server',verbose_name='关联服务器')

    代码优化

    1.公用添加页面

    2.将所有的modlform单独开设文件夹存储

    3.对modelform再次优化 对modelform定义一个父类

    from django.forms import ModelForm
    class BaseModelForm(ModelForm):
        # 将不需要bootstrap样式的字段放入
        exclude_bootstrap = []
        def __init__(self,*args,**kwargs):
            super().__init__(*args,**kwargs)
            # 给字段加上form-control样式
            # self.fields = {'字段名':字段对象}
            for k,field in self.fields.items():
                if k in self.exclude_bootstrap:  # 排除不需要加样式的字段
                    continue
                field.widget.attrs['class'] = 'form-control'
                        
    # 其他modelform书写
    from app01 import models
    from app01.myform.mybase import BaseModelForm
    class ProjectModelForm(BaseModelForm):
        class Meta:
            model = models.Project
            fields = '__all__'

    2.项目管理的增删改查

    项目管理的增删改查大致和服务器类似,只要注意字段的更换就行

  • 相关阅读:
    mysql进阶语句优化---day40
    pymysql基本语法,sql注入攻击,python操作pymysql,数据库导入导出及恢复数据---day38
    单表查询,多表查询,子查询---day37
    mysql-数据类型,类型约束,联合唯一约束,表与表之间的关系,存储引擎---day36
    mysql安装及增删改查操作---day35
    死锁,互斥锁,递归锁,线程事件Event,线程队列Queue,进程池和线程池,回调函数,协程的使用,协程的例子---day33
    进程之间共享数据Manager,线程相关使用Thread,用类定义线程,守护线程setDaemon,线程锁Lock,线程信号量Semaphore---day32
    Docker部署go-fastdfs
    Docker部署gitlab
    Docker部署hasura
  • 原文地址:https://www.cnblogs.com/wangcuican/p/12348577.html
Copyright © 2020-2023  润新知