发布任务模块

一、代码发布任务

发布任务的首页列表

1、models

2、发布任务逻辑分析:

不直接写增删改查

而是在项目管理的查看列表中新增一个发布记录字段,点击该字段查看当前项目所对应的发布记录,

然后在查看页面书写增删改查,这样做的目的就是可以直接针对对应的项目,无需用户自己选择。

对于发布任务单的添加页面,不再使用公共的form.html而是自己单独开设一个,因为需要做额外的扩展

3、url

4、views

5、task_list

发布任务的增加

1、url

2、task_list

3、views

4、myforms

 myforms(校验组件)中的task 对应task _form.html文件

from app01.myforms.base import BaseModelForm
from app01 import models
import datetime
from django import forms


class TaskModelForm(BaseModelForm):class Meta:
        model = models.DeployTask
        fields = '__all__'
        # 指定字段不展示到前端页面
        exclude = ['uid', 'project', 'status']

    def __init__(self, project_obj, *args, **kwargs):
        """当你不知道一个函数或者方法都有哪些参数的时候 就用*args,**kwargs哥俩"""
        super().__init__(*args, **kwargs)
        # 给对象添加额外的属性
        self.project_obj = project_objdef create_uid(self):   #动态生成唯一标识
        # 生成唯一标识
        # luffycity-test-v1-20202020111  如果有项目对象会非常简单
        title = self.project_obj.title
        env = self.project_obj.env
        tag = self.cleaned_data.get('tag')
        current_time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        return "{0}-{1}-{2}-{3}".format(title, env, tag, current_time)

    def save(self, commit=True):
        self.instance.uid = self.create_uid()            
        self.instance.project_id = self.project_obj.pk   # 看上面的__init__
        # 调用父类的save方法保存数据
        super().save(commit)

       

7、发布任务单 界面搭建

我们将添加任务单的界面大致分为三块区域:

基本信息展示区

基本配置

钩子脚本渲染

task_form.html 代码见下:

{% extends 'base.html' %}


{% block css %}
    <style>
        .outline .series .module {
            line-height: 100px;
            vertical-align: middle;
            width: 940px;
            margin: 0 auto;
            padding-bottom: 10px;
        }

        .outline .series .module .item .line {
            float: left;
            width: 80px;

        }

        .outline .series .module .item .line hr {
            margin-top: 49px
        }

        .outline .series .module .item .icon {
            float: left;
            color: #dddddd;
            position: relative;

        }

        .outline .series .module .item .icon .up, .outline .series .module .item .icon .down {
            position: absolute;
            line-height: 49px;
            min-width: 90px;
            left: 0;
            text-align: center;
            margin-left: -38px;
            color: #337ab7;
        }

        .outline .series .module .item:hover .icon, .outline .series .module .item.active .icon {
            color: green;
        }

        .outline .series .module .item .icon .up {
            top: 0;
        }

        .outline .series .module .item .icon .down {
            bottom: 0;

        }
    </style>
{% endblock %}

{% block content %}
    {#    1 基本信息展示区#}
    <table class="table table-hover 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">
                <div>关联服务器</div>
                <ul>
                    {% for server_obj in project_obj.servers.all %}
                        <li>{{ server_obj.hostname }}</li>
                    {% endfor %}
                </ul>
            </td>
        </tr>
        </tbody>
    </table>
    <form action="" method="post" novalidate>
        {% csrf_token %}
        {#    2 基本配置#}
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title"><span class="glyphicon glyphicon-cog"></span>基本配置</h3>
            </div>
            <div class="panel-body form-horizontal">
                <label for="{{ form_obj.tag.id_for_label }}"
                       class="col-md-2 control-label">{{ form_obj.tag.label }}</label>
                <div class="col-md-10">
                    {{ form_obj.tag }}
                    <span style="color: red">{{ form_obj.tag.errors.0 }}</span>
                </div>
            </div>
        </div>
        {#    3 钩子脚本#}
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title"><span class="glyphicon glyphicon-th-list"></span>发布流程&钩子</h3>
            </div>
            <div class="panel-body form-horizontal">
                {#              1 简易流程图区域#}
                <div class="outline">
                    <div class="series">
                        <div class="module clearfix">
                            <div class="item left">
                                <div class="line">
                                    <hr>
                                </div>
                                <div class="icon">
                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
                                    <a class="down">01 开始</a>
                                </div>
                            </div>

                            <div class="item left active">
                                <div class="line">
                                    <hr>
                                </div>
                                <div class="icon">
                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
                                    <a class="up">02 下载前</a>
                                </div>
                            </div>
                            <div class="item left">
                                <div class="line">
                                    <hr>
                                </div>
                                <div class="icon">
                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
                                    <a class="down">03 下载代码</a>
                                </div>
                            </div>

                            <div class="item left active">
                                <div class="line">
                                    <hr>
                                </div>
                                <div class="icon">
                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
                                    <a class="up">04 下载后</a>
                                </div>
                            </div>

                            <div class="item left">
                                <div class="line">
                                    <hr>
                                </div>
                                <div class="icon">
                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
                                    <a class="down">05 打包上传</a>
                                </div>
                            </div>

                            <div class="item left active">
                                <div class="line">
                                    <hr>
                                </div>
                                <div class="icon">
                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
                                    <a class="up">06 发布前</a>
                                </div>
                            </div>

                            <div class="item left">
                                <div class="line">
                                    <hr>
                                </div>
                                <div class="icon">
                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
                                    <a class="down">07 发布</a>
                                </div>
                            </div>

                            <div class="item left active">
                                <div class="line">
                                    <hr>
                                </div>
                                <div class="icon">
                                    <span class="glyphicon glyphicon-record" aria-hidden="true"></span>
                                    <a class="up">08 发布后</a>
                                </div>
                            </div>
                            <div class="item left">
                                <div class="line">
                                    <hr>
                                </div>
                            </div>

                        </div>
                    </div>
                </div>
                {#              2 钩子脚本渲染区域#}
                <div class="hooks">
                    <div class="col-md-6">
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h3 class="panel-title">02 下载前</h3>
                            </div>
                            <div class="panel-body form-horizontal">
                                <div class="form-group">
                                    <div class="col-md-12">
                                        {{ form_obj.before_download_select }}
                                    </div>
                                </div>
                                <div class="form-group">
                                    <div class="col-md-12">
                                        {{ form_obj.before_download_script }}
                                        <span style="color: red">{{ form_obj.before_download_script.errors.0 }}</span>
                                    </div>
                                </div>
                                <div class="form-group" style="height: 60px">
                                    <div class="col-md-3">
                                        <div class="checkbox">
                                            <label>{{ form_obj.before_download_template }}保存为模版</label>
                                        </div>

                                    </div>
                                    <div class="col-md-9">
                                        {{ form_obj.before_download_title }}
                                        <span style="color: red">{{ form_obj.before_download_title.errors.0 }}</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h3 class="panel-title">04 下载后</h3>
                            </div>
                            <div class="panel-body form-horizontal">
                                <div class="form-group">
                                    <div class="col-md-12">
                                        {{ form_obj.after_download_select }}
                                    </div>
                                </div>
                                <div class="form-group">
                                    <div class="col-md-12">
                                        {{ form_obj.after_download_script }}
                                        <span style="color: red">{{ form_obj.after_download_script.errors.0 }}</span>
                                    </div>
                                </div>
                                <div class="form-group" style="height: 60px">
                                    <div class="col-md-3">
                                        <div class="checkbox">
                                            <label>{{ form_obj.after_download_template }}保存为模版</label>
                                        </div>

                                    </div>
                                    <div class="col-md-9">
                                        {{ form_obj.after_download_title }}
                                        <span style="color: red">{{ form_obj.after_download_title.errors.0 }}</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h3 class="panel-title">06 发布前</h3>
                            </div>
                            <div class="panel-body form-horizontal">
                                <div class="form-group">
                                    <div class="col-md-12">
                                        {{ form_obj.before_deploy_select }}
                                    </div>
                                </div>
                                <div class="form-group">
                                    <div class="col-md-12">
                                        {{ form_obj.before_deploy_script }}
                                        <span style="color: red">{{ form_obj.before_deploy_script.errors.0 }}</span>
                                    </div>
                                </div>
                                <div class="form-group" style="height: 60px">
                                    <div class="col-md-3">
                                        <div class="checkbox">
                                            <label>{{ form_obj.before_deploy_template }}保存为模版</label>
                                        </div>

                                    </div>
                                    <div class="col-md-9">
                                        {{ form_obj.before_deploy_title }}
                                        <span style="color: red">{{ form_obj.before_deploy_title.errors.0 }}</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h3 class="panel-title">08 发布后</h3>
                            </div>
                            <div class="panel-body form-horizontal">
                                <div class="form-group">
                                    <div class="col-md-12">
                                        {{ form_obj.after_deploy_select }}
                                    </div>
                                </div>
                                <div class="form-group">
                                    <div class="col-md-12">
                                        {{ form_obj.after_deploy_script }}
                                        <span style="color: red">{{ form_obj.after_deploy_script.errors.0 }}</span>
                                    </div>
                                </div>
                                <div class="form-group" style="height: 60px">
                                    <div class="col-md-3">
                                        <div class="checkbox">
                                            <label>{{ form_obj.after_deploy_template }}保存为模版</label>
                                        </div>

                                    </div>
                                    <div class="col-md-9">
                                        {{ form_obj.after_deploy_title }}
                                        <span style="color: red">{{ form_obj.after_deploy_title.errors.0 }}</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <input type="submit" class="btn btn-success">
    </form>
{% endblock %}


{% block js %}
    <script>
        // 给所有的下拉框绑定文本域改变事件
        // 避免麻烦 直接使用范围查找
        $('.hooks').find('select').change(function () {
            var that = $(this);
            // 发送ajax请求获取脚本内容
            $.ajax({
                url:'/hook/template/' + that.val() + '/',
                type:'get',
                dataType:'JSON',
                success:function (args) {
                    if(args.status){
                        {#alert(args.content)#}
                        // 将脚本内容通过DOM操作渲染到对应的文本框中
                        that.parent().parent().next().find('textarea').val(args.content)
                    }
                }

            })
        })
    </script>
{% endblock %}
发布任务界面

 

8、

 

 

 9、task_form.html文件中:

 

 

 

 

 

 10、问题:

我们前面写的taskmodelform中,没有下拉框,checkbox和模版文本框

我们需要去taskmodelform中额外的定义这些字段

11、解决:在 myforms(校验组件)中的task 自定义额外的字段类型

from app01.myforms.base import BaseModelForm
from app01 import models
import datetime
from django import forms


class TaskModelForm(BaseModelForm):

    """自定义额外的字段类型"""
    # 无需添加form-control的字段
    exclude_bootstrap = [
        'before_download_template',
        'after_download_template',
        'before_deploy_template',
        'after_deploy_template'

    ]
    # 每一个钩子脚本都需要额外的添加 下拉框 checkbox 文本框
    before_download_select = forms.ChoiceField(required=False, label='下载前')
    before_download_title = forms.CharField(required=False, label='模板名称')
    before_download_template = forms.BooleanField(required=False, widget=forms.CheckboxInput, label='是否保存为模板')

    after_download_select = forms.ChoiceField(required=False, label='下载后')
    after_download_title = forms.CharField(required=False, label='模板名称')
    after_download_template = forms.BooleanField(required=False, widget=forms.CheckboxInput, label='是否保存为模板')

    before_deploy_select = forms.ChoiceField(required=False, label='发布前')
    before_deploy_title = forms.CharField(required=False, label='模板名称')
    before_deploy_template = forms.BooleanField(required=False, widget=forms.CheckboxInput, label='是否保存为模板')

    after_deploy_select = forms.ChoiceField(required=False, label='下载后')
    after_deploy_title = forms.CharField(required=False, label='模板名称')
    after_deploy_template = forms.BooleanField(required=False, widget=forms.CheckboxInput, label='是否保存为模板')

    class Meta:
        model = models.DeployTask
        fields = '__all__'
        # 指定字段不展示到前端页面
        exclude = ['uid', 'project', 'status']

 

在task_form.html中写下拉框代码:

 

 

 还有改其他task_form.html的代码  。

 myforms(校验组件)中的task 给下拉框数据

   def __init__(self,project_obj,*args,**kwargs):
        """当你不知道一个函数或者方法都有哪些参数的时候 就用*args,**kwargs哥俩"""
        super().__init__(*args,**kwargs)
        # 给对象添加额外的属性
        self.project_obj = project_obj

        # 给下拉框添加数据  <option value="0">请选择</option>
        self.fields['before_download_select'].choices = [(0,'请选择')]
        self.fields['after_download_select'].choices = [(0,'请选择')]
        self.fields['before_deploy_select'].choices = [(0,'请选择')]
        self.fields['after_deploy_select'].choices = [(0,'请选择')]

二、钩子模版的保存及前端动态展示的功能

下拉框中点击脚本名称就会去后端请求对于的脚本内容

也就意味着我们应该开设一张专门用来存储钩子脚本内容的表

 

 

      1、models

 

 

      2、在 myforms(校验组件)中的task中的save方法中  判断

当用户点击了checkbox按钮的时候,就应该去操作上面的表来存储脚本内容

我们在后端只需要判断用户是否点击了,再做相应的处理即可。

def save(self, commit=True):
        self.instance.uid = self.create_uid()
        self.instance.project_id = self.project_obj.pk
        # 调用父类的save方法保存数据
        super().save(commit)

        # 判断用户是否点击了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
            )

 

      3、下拉框如何展示对应的钩子脚本文件名

在 myforms(校验组件)中的task中的__init__方法中  

    def __init__(self, project_obj, *args, **kwargs):
        """当你不知道一个函数或者方法都有哪些参数的时候 就用*args,**kwargs哥俩"""
        super().__init__(*args, **kwargs)
        # 给对象添加额外的属性
        self.project_obj = project_obj

        # 给下拉框添加数据  <option value="0">请选择</option>
        before_download = [(0, '请选择')]
        extra_choices = models.HookTemplate.objects.filter(hook_type=2).values_list('pk','title')  # [(),()]
        before_download.extend(extra_choices)
        self.fields['before_download_select'].choices = before_download

        after_download = [(0, '请选择')]
        extra_choices = models.HookTemplate.objects.filter(hook_type=4).values_list('pk', 'title')  # [(),()]
        after_download.extend(extra_choices)
        self.fields['after_download_select'].choices = after_download

        before_deploy = [(0, '请选择')]
        extra_choices = models.HookTemplate.objects.filter(hook_type=6).values_list('pk', 'title')  # [(),()]
        before_deploy.extend(extra_choices)
        self.fields['before_deploy_select'].choices = before_deploy

        after_deploy = [(0, '请选择')]
        extra_choices = models.HookTemplate.objects.filter(hook_type=8).values_list('pk', 'title')  # [(),()]
        after_deploy.extend(extra_choices)
        self.fields['after_deploy_select'].choices = after_deploy

 

      4、选择钩子脚本文件名展示对应的脚本内容

在 task_form.html文件中,利用事件操作(文本域改变事件)和ajax实现动态展示

 

 

后端:url

 

 views

 

 

 

 

      5、当用户点击了保存模版,但是没有填写脚本内容的时候,应该作出相应的提示信息

            重写clean方法(局部钩子 全局钩子)  在 myforms(校验组件)中的task中的写局部钩子方法中 

     

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','请输入模版名称')

 

 

提示信息没有足够的位置展示,会出现页面错乱的情况

提前给提示信息预留位置,添加一个高度

 

 

posted @ 2020-04-19 22:52  薛定谔的猫66  阅读(341)  评论(0)    收藏  举报