老男孩上海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
前端用户选择不同的下拉框里面的内容,动态展示脚本内容,方便用户查看和进一步的修改
<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','请输入模版名称')