代码发布系统三

  • django基于channels完成群聊功能

    后端框架不一定默认支持websocket

    三步走前期配置

    """
    http协议还是走 urls.py 与 views.py
    /index/          index
    浏览器地址栏输入网址即可
    
    websocket协议走routing.py 与 consumers.py
    /chat/ 					 ChatConsumer
    借助于js内置对象new WebSocket('ws://127.0.0.1:8080/chat/')
    """
    

    需要掌握的方法

    后端

    from channels.generic.websocket import WebSocketConsumer
    from channels.exceptions import StopConsumer
    
    class ChatConsumer(WebSocketConsumer):
      def websocket_connect(self,message):
        # 客户端请求链接自动触发
        self.accept()
      
      def websocket_receive(self,message):
        # 客户端发送消息自动触发 message是一个字典{'type':'','text':客户端消息}
        self.send(text_data='给客户端回复的消息')
      
      def websocket_disconnect(self,message):
        # 客户端断开链接之后自动触发
        raise StopConsumer
    

    前端

    <script>
    	var ws = new WebSocket('ws://127.0.0.1:8080/chat/');
      
      // 1 客户端握手环节成功之后 自动触发
      ws.onopen = function(){}
      
      // 2 给服务端发送消息
      ws.send()
      
      // 3 服务端回复消息 自动触发
      ws.onmessage = function(){}
      
      // 4 主动断开链接自动触发
      ws.onclose = function(){
    </script>
    
  • gojs插件

    后续如果业务逻辑需要使用更多的图标,那么你可以参考官网

    基本概念

    • TextBlock
    • Shape
    • Node
    • Links

    gojs的使用规律,先在html页面上用div占据一块区域,之后所有的渲染操作全部在该div内部进行

    数据绑定

    • 数据格式是列表套字典
    • 修改图标样式 只需要提供唯一标示key和修改参数即可

    去除水印

    打开go.js文件,查找特定的一个字符串

    注释掉或者直接删掉该字符串所在的一段代码

    然后在注释或者删除的后面添加一段新的代码

    a.kr = function(){return false};
    
  • paramiko模块

    通过ssh远程连接服务器并操作服务器

    执行命令

    上传下载文件

    该模块也是很多运维工具底层实现的原理 ansible

    该模块即支持用户名密码的方式 也支持公钥私钥的方式

    需要你掌握的就是我们封装之后的SSHProxy类代码,之后只要涉及到paramiko连接服务器直接拷贝使用即可

    面向对象试题

    # 对象执行with上下文管理的时候 会自动触发__enter__,__exit__方法
    
  • gitpython模块

    需要你掌握的就是我们封装之后的类代码,之后只要涉及到操作远程仓库直接拷贝使用即可

内容概要

  • 服务器管理
  • 项目管理
  • 发布任务管理
  • 发布任务执行流程动态展示到前端

扩展知识点:当服务器特别多的时候从平台下载数据,如何减轻平台的压力

最新的技术点是p2p技术也叫比特流技术

所有人都可以成为数据的下载者以及上传者

为什么有时候下载电影速度快,有时候慢,快的时候可能是因为你的室友电脑里面就有该资源,你就是从你室友的电脑中下载的,慢的时候则是因为你的周边都没有该资源的提供者

内容详细

主要是用modelform实现服务器及项目的增删改查操作

服务器管理

为了解耦合以及项目逻辑更加清晰

将全局的templates文件夹剔除,在应用内创建自己的templates文件夹,并且将应用里面的views.py删除

创建views文件夹,里面根据功能的不用创建不同的py文件

数据校验

前端字段标签渲染

展示错误信息

forms组件 >>> modelform组件

扩展知识点

return redirect('server_list')
# redirect括号内可以直接写url 其实也可以写反向解析的别名 但是如果带有名无名分组的情况 则必须使用reverse

django默认的语言环境是英文,但是它的内部提供很多国家的语言环境,你可以修改

# 配置文件中修改参数
# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans'

"""django内部能够支持的语言环境 可以查看它的全局配置文件"""
from django.conf import global_settings
LANGUAGE_CODE = 'en-us'

# Languages we provide translations for, out of the box.
LANGUAGES = [
    ('af', gettext_noop('Afrikaans')),
    ('ar', gettext_noop('Arabic')),
    ('ast', gettext_noop('Asturian')),
  	...
]

modelform编辑功能非常简单,只需要你给一个instance参数即可

def server_edit(request,edit_id):
    # 获取编辑对象 展示到页面给用户看 之后用户再编辑 提交
    edit_obj = models.Server.objects.filter(pk=edit_id).first()
    """
    其实编辑页面和添加页面是一样的 不同的在于是否需要渲染默认数据
    所以我们直接使用用一个页面
    """
    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()  # 编辑
            # 新增和编辑都是save方法 区分就依据与instance参数
            return redirect('server_list')
    return render(request,'form.html',locals())

删除功能需要做二次确认

并且删除完成后需要让用户能够直观的在浏览器上看到数据被删除了

不能直接刷新页面,因为如果是分页的情况,刷新页面之后肯定是在第一页

如果我是在第99页删除了1条数据,数据删除并且还在99页

<script>
        function removeData(ths,delete_id) {
            var res = confirm('是否确定删除?');
            // 返回值 判断用户点击的确定还是取消
            if(res){
                // 朝后端发送删除数据的请求
                $.ajax({
                    url:'/server/delete/' + delete_id + '/',
                    type:'get',
                    dataType:'JSON',
                    success:function (args) {
                        if(args.status){
                             // 通过DOM操作 来删除页面数据
                            $(ths).parent().parent().remove()
                        }
                    }
                })
            }
        }
</script>

项目管理

class Project(models.Model):
    """项目表"""
    # luffycity  cmdb crm ...
    title = models.CharField(verbose_name='项目名',max_length=32)
    
    # https://www.github.com/xxx.git/
    repo = models.CharField(verbose_name='仓库地址',max_length=32)
    
    env_choices = (
        ('prod','正式'),
        ('test','测试'),
    )
    env = models.CharField(verbose_name='环境',max_length=16,choices=env_choices,default='test')

针对项目表的增删改查直接拷贝服务器表的代码修改即可

项目优化

不要上来就做优化,一定是用简单最lowb的方式将代码写好之后,再考虑优化的问题

  • 视图函数与modelform应该区分开

    """
    app01
    	-myforms
    		--project.py
    		--server.py
    """
    
  • 整合服务器modelform和项目modelform类相同的代码 抽成基类

    """
    什么是类
    	类是对象公共的属性与技能的结合体
    什么是基类
    	基类是类公共的属性与技能的结合体
    """
    from django.forms import ModelForm
    
    # 父类
    class BaseModelForm(ModelForm):
        # 将是否添加样式 做成可配置的
        exclude_bootstrap = []
        # 重写init方法  当你不知道一个方法是否有参数或者有几个参数的时候 建议你写*args,**kwargs
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # 额外的操作
            # print(self.fields)  # 有序字典 OrderedDict([('hostname', <django.forms.fields.CharField object at 0x1092abf60>)])
            # 给所有的字段添加样式form-control
            for k, field in self.fields.items():
                # 判断当前字段是否需要加
                if k in self.exclude_bootstrap:
                    # 直接跳过
                    continue
                field.widget.attrs['class'] = 'form-control'
                
    # 子类
    from app01 import models
    from app01.myforms.base import BaseModelForm
    
    
    class ProjectModelForm(BaseModelForm):
        class Meta:
            model = models.Project
            fields = "__all__"
    
  • 项目表需要再添加几个字段

    		# /data/temp/...
        path = models.CharField(verbose_name='线上项目地址',max_length=32)
        # 项目跑在服务器上  那么项目和服务器应该是有关系的
        """
        一个项目可以是否可以跑在多台服务器上   可以!
        一台服务器上是否可以跑多个项目呢      当资金不是很充足的时候 服务器是可以混用的 可以!
        """
        servers = models.ManyToManyField(verbose_name='关联服务器',to='Server')
    

发布任务单

class DeployTask(models.Model):
    """发布任务单
    项目主键            项目版本
    1                      v1
    1                      v2
    1                      v3
    2                      v1
    """
    # luffycity-test-v1-20201111111
    """项目名-环境-版本-日期"""
    uid = models.CharField(verbose_name='标识',max_length=32)

    # 任务与项目是一对多的关系  并且任务是多 项目是一
    project = models.ForeignKey(verbose_name='项目',to='Project')

    tag = models.CharField(verbose_name='版本',max_length=32)

    status_choices = (
        (1,'待发布'),
        (2,'发布中'),
        (3,'成功'),
        (4,'失败'),
    )
    status = models.IntegerField(verbose_name='状态',choices=status_choices,default=1)

    """预留了一些钩子功能"""
    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)

猜你喜欢

转载自www.cnblogs.com/mqhpy/p/12564247.html