代码发布 day04

老男孩上海py11期代码发布直播课

昨日内容回顾

  • python操作git(gitpython模块)

    # 安装
    pip3 install gitpython
    
    # 常用操作
    """参考昨日笔记"""
    
    # 将所有零散的功能整合到了一个类中
    """参考昨日笔记,用到的时候直接CV即可"""
  • 服务器管理(主要是为了搭建后续增删改查业务逻辑)

    # 先项目一般情况下都是从数据库建表开始
    
    # 增删改查
    """
    技术点
      1.modelform实现整体的增删改查
          class MyModelForm(ModelForm):
              class Meta:
                  model = models.Userinfo
                  fields = '__all__'
                  # 排除额外的字段
                  exclude = ['info']
      2.modelform的使用跟forms组件一模一样
          # 新增
          form_obj = MyModelForm(data=request.POST)
          # 编辑
          form_obj = MyModelForm(instance=edit_obj)
    
          form_obj = MyModelForm(data=request.POST,instance=edit_obj)
          form_obj.save() 
    """
  • 项目管理(完全是拷贝服务器管理代码,稍微修改了一部分)

    # 直接拷贝服务器管理的所有代码,修改名称即可
  • 代码优化

    """
    1.公用一个添加页面(其实编辑页可以不需要)
    2.将modelform的代码整合到一个固定的文件夹下做解耦合
      -myforms
          --server.py
          --project.py
    3.将多个modelform类中相同的代码整合产生基类
      目的:
          1.减少后续modelform创建书写的代码量
          2.之后只需要在基类中书写一份代码,所有的子类都会有相应的属性或方法
    """
  • 发布任务表创建

    class DeployTask(models.Model):
        """
        发布任务单
        项目主键            项目版本
        1                      v1
        1                      v2
        1                      v3
        2                      v1
        2                      v2
        """
        # 唯一标识  项目名-环境-版本号-创建时间
        # luffy-test-v1-202020202222  不需要用户填写 后续代码自动生成
        uid = models.CharField(max_length=128,verbose_name='标识')
    
        project = models.ForeignKey(to='Project',verbose_name='项目')
    
        tag = models.CharField(max_length=16,verbose_name='版本')
    
        # 任务单 可能出现的状态
        status_choices = (
            (1,'待发布'),
            (2,'发布中'),
            (3,'成功'),
            (4,'失败'),
        )
        status = models.IntegerField(verbose_name='状态',choices=status_choices,default=1)
    
        # 我在发布的流程中 设置了几个钩子节点 方便用户在不同阶段可以进行额外的操作  定义多少及哪些阶段 具体看业务需求
        # 步骤3:预留钩子功能字段  项目有多种python、java、php、vue大体一致但小细节有区别
        before_download_script = models.TextField(verbose_name='下载前脚本', null=True, blank=True)
        after_download_script = models.TextField(verbose_name='下载后脚本', null=True, blank=True)
        before_deploy_script = models.TextField(verbose_name='发布前脚本', null=True, blank=True)
        after_deploy_script = models.TextField(verbose_name='发布后脚本', null=True, blank=True)

今日内容

  • 发布任务单功能书写
    • 单独的添加页面
    • 针对脚本钩子功能需要做很多处理
  • channels实时发布(channel-layers)
  • gojs实时展示状态

内容详细

发布任务单,针对发布任务单的增删改查,我们不直接做

不直接写任务单的添加页面,而是在项目的展示页上面新增一个查看当前项目任务纪录的字段

点击跳转到当前项目所有的发布纪录的查看页面,之后渲染添加按钮并且携带当前项目的主键值,这样的话就能够实时绑定项目与发布任务

简易版本的添加功能:直接公用之前的form.html页面

项目优化

  • 添加功能,uid和project_id字段,我们重写save方法自动添加

  • 不再使用公用的form.html而是单独创建任务单独有的添加页面

    """添加页面分成三块区域
    
    1.第一块区域展示当前创建任务单关联的项目的基本信息
        <table class="table-hover table table-bordered table-striped">
            <tbody>
                <tr>
                    <td>项目名称:{{ project_obj.title }}</td>
                    <td>环境:{{ project_obj.get_env_display }}</td>
                </tr>
                <tr>
                    <td colspan="2">仓库地址:{{ project_obj.repo }}</td>
                </tr>
                <tr>
                    <td colspan="2">线上路径:{{ project_obj.path }}</td>
                </tr>
                <tr>
                    <td colspan="2">
                        <p>关联服务器</p>
                        <ul>
                            {% for server_obj in project_obj.servers.all %}
                                <li>{{ server_obj.hostname }}</li>
                            {% endfor %}
    
                        </ul>
                    </td>
                </tr>
            </tbody>
        </table>
    
    2.基础配置
    前端页面的渲染,代码你可以不掌握,或者自己写页面
    
    2.1.唯一标识动态创建
      # 用来产生唯一标识
        def create_uid(self):
            # 项目名-环境-版本号-创建时间
            title = self.project_obj.title
            env = self.project_obj.env
            # 版本号 需要从数据提交的数据中获取
            tag = self.cleaned_data.get('tag')
            date_time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
            return '{0}-{1}-{2}-{3}'.format(title,env,tag,date_time)
    
    3.钩子模版的渲染及功能完善
      1.你只需要将页面调整好一个 之后直接拷贝即可
    
      2.给下拉框添加默认的选择项
    
      3.保存用户书写的钩子脚本内容
    """

    我们需要单独开设一张表专门用来存储脚本内容

    class HookTemplate(models.Model):
        """钩子模版"""
        title = models.CharField(verbose_name='标题',max_length=64)
        # 脚本内容 其实就是文件内容 文件内容大小不确定 可能是大段的文本
        content = models.TextField(verbose_name='脚本内容')
        # 由于我们要对钩子进行分类管理 钩子与钩子之间模版是不影响的
        hook_type_choices = (
            (2,'下载前'),
            (4,'下载后'),
            (6,'发布前'),
            (8,'发布后'),
        )
        hook_type = models.IntegerField(verbose_name='钩子类型',choices=hook_type_choices)

    点击提交按钮,需要保存钩子模版如果用户有书写的话

    所以接下来我们需要去操作save方法

    # 通过用户是否点击了checkbox来判断是否需要操作钩子模版表
            if self.cleaned_data.get('before_download_template'):
                title = self.cleaned_data.get('before_download_title')
                content = self.cleaned_data.get('before_download_script')
                models.HookTemplate.objects.create(title=title,content=content,hook_type=2)
    
            if self.cleaned_data.get('after_download_template'):
                title = self.cleaned_data.get('after_download_title')
                content = self.cleaned_data.get('after_download_script')
                models.HookTemplate.objects.create(title=title,content=content,hook_type=4)
    
            if self.cleaned_data.get('before_deploy_template'):
                title = self.cleaned_data.get('before_deploy_title')
                content = self.cleaned_data.get('before_deploy_script')
                models.HookTemplate.objects.create(title=title,content=content,hook_type=6)
    
            if self.cleaned_data.get('after_deploy_template'):
                title = self.cleaned_data.get('after_deploy_title')
                content = self.cleaned_data.get('after_deploy_script')
                models.HookTemplate.objects.create(title=title,content=content,hook_type=8)

    下拉框展示对应模版名称

    before_download = [(0,'请选择'),]
            # 给select框添加选项 数字就是option里面value值 字符串就是展示给用户看的信息
            # <option value="0">请选择</option>
            # 动态从数据库中获取当前钩子节点对应的所有的模版名称
            before_download.extend(models.HookTemplate.objects.filter(hook_type=2).values_list('pk','title'))
            self.fields['before_download_select'].choices = before_download

    前端用户选择不同的下拉框里面的内容,动态展示脚本内容,方便用户查看和进一步的修改

    扫描二维码关注公众号,回复: 10001395 查看本文章
    <script>
            // 给下拉框绑定文本域改变事件  change  省市联动
            $('.hooks').find('select').change(function () {
                // alert($(this).val())  用户选择的模版的主键值
                // 获取用户选择的模版数据的主键值 发送给后端 后端查询出结果返回给前端
                var $this = $(this);
                $.ajax({
                    url:'/hook/template/'+$(this).val()+'/',
                    type:'get',
                    dataType:'JSON',
                    success:function (args) {
                        // 前端通过DOM操作将脚本内容渲染到对应的Textarea框中
                        $this.parent().parent().next().find('textarea').val(args.content)
                    }
                })
    
    
            })
        </script>

    用户点击了checkbox之后,那么模版的名称就必须填写不能为空

    # 利用全局钩子校验
    # 需要校验多个字段数据
        def clean(self):
            if self.cleaned_data.get('before_download_template'):
                # 获取模版 名称 判断是否为空
                title = self.cleaned_data.get('before_download_title')
                if not title:
                    # 展示错误信息
                    self.add_error('before_download_title','请输入模版名称')
    
            if self.cleaned_data.get('after_download_template'):
                # 获取模版 名称 判断是否为空
                title = self.cleaned_data.get('after_download_title')
                if not title:
                    # 展示错误信息
                    self.add_error('after_download_title','请输入模版名称')
    
            if self.cleaned_data.get('before_deploy_template'):
                # 获取模版 名称 判断是否为空
                title = self.cleaned_data.get('before_deploy_title')
                if not title:
                    # 展示错误信息
                    self.add_error('before_deploy_title','请输入模版名称')
    
            if self.cleaned_data.get('after_deploy_template'):
                # 获取模版 名称 判断是否为空
                title = self.cleaned_data.get('after_deploy_title')
                if not title:
                    # 展示错误信息
                    self.add_error('after_deploy_title','请输入模版名称')

猜你喜欢

转载自www.cnblogs.com/le-le666/p/12534250.html