20200317 Use of code release module

abstract

* django基于channels实现群聊功能

* gojs插件

  都给你们封装了代码,直接拷贝使用即可

* paramiko模块

  都给你们封装了代码,直接拷贝使用即可

* gitpython模块

  都给你们封装了代码,直接拷贝使用即可

Django implements group chat based on channels

First configure channels in three steps

Backend method

  • websocket_connect() Triggered when connected
  • websocket_receive() Triggered when the front end sends a message
  • websocket_disconnect() Triggered when disconnected
class ProtocolTypeRouter:
    """
    Takes a mapping of protocol type names to other Application instances,
    and dispatches to the right one based on protocol name (or raises an error)
    """
    def __init__(self, application_mapping):
        self.application_mapping = application_mapping
        if "http" not in self.application_mapping:
            self.application_mapping["http"] = AsgiHandler

routing.py file

from channels.routing import ProtocolTypeRouter,URLRouter
from django.conf.urls import url
from app01 import consumers

application = ProtocolTypeRouter({
    'websocket':URLRouter([
        url(r'^chat/$',consumers.ChatConsumer)
    ])
})

consumers.py file

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer


consumer_object_list = []

class ChatConsumer(WebsocketConsumer):
    def websocket_connect(self, message):
        """请求websocket链接的时候自动触发"""
        # print('请求链接')
        self.accept()  # 与客户端建立链接

        # 链接成功之后 就将当前链接对象添加到列表中
        consumer_object_list.append(self)

    def websocket_receive(self, message):
        """前端浏览器发送消息自动触发"""
        # print(message)  # 消息字典  {'type': 'websocket.receive', 'text': 'hahahaha'}
        # 聊天数据
        text = message.get('text')
        # 给当前客户端发消息  单发
        # self.send(text_data=text)

        # 循环一个个对象 发送  群发
        for obj in consumer_object_list:
            obj.send(text_data=text)

    def websocket_disconnect(self, message):
        """断开websocket链接自动触发"""
        print('断开链接')
        # 将当前断开链接的对象从列表中移除
        consumer_object_list.remove(self)
        raise StopConsumer

Front-end method

http协议
	index					>>>			index函数
	访问:浏览器地址栏输入地址直接访问
	
websocket协议
	chat					>>>			ChatConsumer类(3个方法)
	访问:利用js内置对象new WebSocket('ws://127.0.0.1:8080/chat/')
  • Automatically triggered after successful onopen link
  • send send data
  • onmessage server sends data automatically triggered
  • close browser disconnect
<script>
    // 生产内置对象
    var ws = new WebSocket('ws://127.0.0.1:8000/chat/');

    // 1 握手环节成功之后自动触发  onopen
    ws.onopen = function () {
        console.log('链接成功')
    };
    // 2 发送数据       send
    function sendMsg() {
        ws.send($('#d1').val())
    }

    // 3 服务端发送数据自动触发   onmessage
    ws.onmessage = function (args) {
        // alert(args)  // args不是真正的数据对象 真正的数据在该对象的data属性中
        alert(args.data)
    };
    // 4 浏览器断开链接        close
    ws.onclose = function () {
        ws.close()
    }
</script>

Mass sending function lowb version

Maintain a global list, add it to the list once the client links, and then loop the list object to send messages to each client link object when replying to the message to achieve group sending

In fact, the group sending function, the official has provided a method channel-layers (we will talk about it when writing code)

to sum up

# 后端三个方法
websocket_connect
websocket_receive
websocket_disconnect

# 前端四个方法
onopen
send
onmessage
onclose

gojs plugin

Introduction

Just a front-end plugin

If you want to use it, you need to go to the official website to download the corresponding js file: https://gojs.net/latest/index.html

Not all js files are used after downloading, we need to understand that there are only three

"""
go.js				 正常必须要导入的文件
go-debug.js  会展示报错消息 类似于debug模式 线上肯定不会使用
Figures.js	 扩展图表(go.js自带的图表比较少,如果出现图标显示不出来的情况)
"""
# 总结:使用的时候导入go.js和Figures.js就不会有任何问题了

Fixed routine: first use div to delineate the area on the page, then all gojs chart rendering is done inside the div

<div id="myDiagramDiv" style="width:500px; height:350px; background-color: #DAE4E4;"></div>
<script src="go.js"></script>
<script>
  var $ = go.GraphObject.make;
  // 第一步:创建图表
  var myDiagram = $(go.Diagram, "myDiagramDiv"); // 创建图表,用于在页面上画图
  // 第二步:创建一个节点,内容为jason
  var node = $(go.Node, $(go.TextBlock, {text: "jason"}));
  // 第三步:将节点添加到图表中
  myDiagram.add(node)
</script>

use

  • TextBlock create text
  • Shape graphics
  • Node (combination of text and graphics)
  • Link Arrow

TextBlock

<div id="myDiagramDiv" style="width:500px; height:350px; background-color: #DAE4E4;"></div>
<script src="go.js"></script>
<script>
    var $ = go.GraphObject.make;
    // 第一步:创建图表
    var myDiagram = $(go.Diagram, "myDiagramDiv"); // 创建图表,用于在页面上画图

    var node1 = $(go.Node, $(go.TextBlock, {text: "jason"}));
    myDiagram.add(node1);
    var node2 = $(go.Node, $(go.TextBlock, {text: "jason", stroke: 'red'}));
    myDiagram.add(node2);
    var node3 = $(go.Node, $(go.TextBlock, {text: "jason", background: 'lightblue'}));
    myDiagram.add(node3);
</script>

Shape

<div id="myDiagramDiv" style="width:500px; height:350px; background-color: #DAE4E4;"></div>
<script src="go.js"></script>
<script src="Figures.js"></script>
<script>
    var $ = go.GraphObject.make;
    // 第一步:创建图表
    var myDiagram = $(go.Diagram, "myDiagramDiv"); // 创建图表,用于在页面上画图

    var node1 = $(go.Node,
        $(go.Shape, {figure: "Ellipse", width: 40, height: 40})
    );
     myDiagram.add(node1);

     var node2 = $(go.Node,
        $(go.Shape, {figure: "RoundedRectangle", width: 40, height: 40, fill: 'green',stroke:'red'})
    );
    myDiagram.add(node2);

    var node3 = $(go.Node,
        $(go.Shape, {figure: "Rectangle", width: 40, height: 40, fill: null})
    );
    myDiagram.add(node3);

    var node5 = $(go.Node,
        $(go.Shape, {figure: "Club", width: 40, height: 40, fill: 'red'})
    );
    myDiagram.add(node5);
</script>

node

<div id="myDiagramDiv" style="width:500px; height:350px; background-color: #DAE4E4;"></div>
<script src="go.js"></script>
<script src="Figures.js"></script>
<script>
    var $ = go.GraphObject.make;
    // 第一步:创建图表
    var myDiagram = $(go.Diagram, "myDiagramDiv"); // 创建图表,用于在页面上画图

    var node1 = $(go.Node,
         "Vertical",  // 垂直方向
        {
            background: 'yellow',
            padding: 8
        },
        $(go.Shape, {figure: "Ellipse", width: 40, height: 40,fill:null}),
        $(go.TextBlock, {text: "jason"})
    );
    myDiagram.add(node1);

    var node2 = $(go.Node,
        "Horizontal",  // 水平方向
        {
            background: 'white',
            padding: 5
        },
        $(go.Shape, {figure: "RoundedRectangle", width: 40, height: 40}),
        $(go.TextBlock, {text: "jason"})
    );
    myDiagram.add(node2);

    var node3 = $(go.Node,
        "Auto",  // 居中
        $(go.Shape, {figure: "Ellipse", width: 80, height: 80, background: 'green', fill: 'red'}),
        $(go.TextBlock, {text: "jason"})
    );
    myDiagram.add(node3);

</script>
<div id="myDiagramDiv" style="width:500px; min-height:450px; background-color: #DAE4E4;"></div>
    <script src="go.js"></script>
    <script>
        var $ = go.GraphObject.make;

        var myDiagram = $(go.Diagram, "myDiagramDiv",
            {layout: $(go.TreeLayout, {angle: 0})}
        ); // 创建图表,用于在页面上画图

        var startNode = $(go.Node, "Auto",
            $(go.Shape, {figure: "Ellipse", width: 40, height: 40, fill: '#79C900', stroke: '#79C900'}),
            $(go.TextBlock, {text: '开始', stroke: 'white'})
        );
        myDiagram.add(startNode);

        var downloadNode = $(go.Node, "Auto",
            $(go.Shape, {figure: "RoundedRectangle", height: 40, fill: 'red', stroke: '#79C900'}),
            $(go.TextBlock, {text: '下载代码', stroke: 'white'})
        );
        myDiagram.add(downloadNode);

        var startToDownloadLink = $(go.Link,
            {fromNode:downloadNode, toNode:startNode,},
            $(go.Shape, {strokeWidth: 1}),
            $(go.Shape, {toArrow: "OpenTriangle", fill: null, strokeWidth: 1})
        );
        myDiagram.add(startToDownloadLink);
    </script>

Thinking: we want to dynamically generate charts and dynamically modify icon messages and status, the data should come from the back end

So parse to provide a way to interact with front-end and back-end data

Data binding

<div id="diagramDiv" style="width:100%; min-height:450px; background-color: #DAE4E4;"></div>

    <script src="go.js"></script>
    <script>
        var $ = go.GraphObject.make;
        var diagram = $(go.Diagram, "diagramDiv",{
            layout: $(go.TreeLayout, {
                angle: 0,
                nodeSpacing: 20,
                layerSpacing: 70
            })
        });
        // 生成一个节点模版
        diagram.nodeTemplate = $(go.Node, "Auto",
            $(go.Shape, {
                figure: "RoundedRectangle",
                fill: 'yellow',
                stroke: 'yellow'
            }, new go.Binding("figure", "figure"), new go.Binding("fill", "color"), new go.Binding("stroke", "color")),
            $(go.TextBlock, {margin: 8}, new go.Binding("text", "text"))
        );
        // 生成一个箭头模版
        diagram.linkTemplate = $(go.Link,
            {routing: go.Link.Orthogonal},
            $(go.Shape, {stroke: 'yellow'}, new go.Binding('stroke', 'link_color')),
            $(go.Shape, {toArrow: "OpenTriangle", stroke: 'yellow'}, new go.Binding('stroke', 'link_color'))
        );
        // 数据集合  以后替换ajax请求   注意使用key和parent来规定箭头的指向
        var nodeDataArray = [
            {key: "start", text: '开始', figure: 'Ellipse', color: "lightgreen"},
            {key: "download", parent: 'start', text: '下载代码', color: "lightgreen", link_text: '执行中...'},
            {key: "compile", parent: 'download', text: '本地编译', color: "lightgreen"},
            {key: "zip", parent: 'compile', text: '打包', color: "red", link_color: 'red'},
            {key: "c1", text: '服务器1', parent: "zip"},
            {key: "c11", text: '服务重启', parent: "c1"},
            {key: "c2", text: '服务器2', parent: "zip"},
            {key: "c21", text: '服务重启', parent: "c2"},
            {key: "c3", text: '服务器3', parent: "zip"},
            {key: "c31", text: '服务重启', parent: "c3"},
        ];
        diagram.model = new go.TreeModel(nodeDataArray);

        // 动态控制节点颜色变化   后端给一个key值 即可查找图表并修改
        var node = diagram.model.findNodeDataForKey("zip");
        diagram.model.setDataProperty(node, "color", "lightgreen");
    </script>

to sum up

"""
通过数据绑定的方式就可以实现前后端交互的形式
"""

How to remove the watermark that comes with gojs

You need to modify the source code of the js file

Find the fixed string in the js file 7eba17a4ca3b1a8346

/*a.kr=b.V[Ra("7eba17a4ca3b1a8346")][Ra("78a118b7")](b.V,Jk,4,4);*/

Comment the line of code where the string is

And add a new line of code

a.kr=function(){return false};

paramiko module

Connect to the server remotely via ssh and execute the response command, similar to Xshell

Ansible is used to manage remote servers in batches, and the bottom one is the paramiko module.

installation

pip3 install paramiko

use

The paramiko module supports the user name and password to operate the server

Also supports public key and private key to operate the server

And in actual production, public and private keys are used more, because the password is sensitive information

Excuting an order

"""执行命令  用户名和密码的方式"""
# 创建对象
ssh = paramiko.SSHClient()
# 允许链接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())


# 链接服务器
ssh.connect(hostname='172.16.219.173',port=22,username='root',password='jason123')

# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls /')
"""
stdin用来输入额外的命令 
    yum install ansible  额外的命令-y
stdout命令的返回结果  正确
stderr命令的返回结果  错误
"""
res = stdout.read()  # 网络传输过来的二进制数据
print(res.decode('utf-8'))

# 关闭链接
ssh.close()



# 公钥和私钥(先讲公钥保存到服务器上)
import paramiko

# 读取本地私钥
private_key = paramiko.RSAKey.from_private_key_file('a.txt')

# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='172.16.219.173', port=22, username='root', pkey=private_key)

# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls /')
# 获取命令结果
result = stdout.read()
print(result.decode('utf-8'))
# 关闭连接
ssh.close()

Upload and download files

"""上传下载文件  用户名和密码的方式"""
import paramiko

# 用户名和密码
transport = paramiko.Transport(('172.16.219.173', 22))
transport.connect(username='root', password='jason123')

sftp = paramiko.SFTPClient.from_transport(transport)

# 上传文件
# sftp.put("a.txt", '/data/b.txt')  # 注意上传文件到远程某个文件下 文件必须存在

# 下载文件
sftp.get('/data/b.txt', 'c.txt')  # 将远程文件下载到本地并重新命令
transport.close()



"""上传下载文件 公钥私钥的方式"""
# 公钥和私钥
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('c.txt')
transport = paramiko.Transport(('172.16.219.173', 22))
transport.connect(username='root', pkey=private_key)
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
# sftp.put('manage.py', '/data/temp.py')

# 将remove_path 下载到本地 local_path
# sftp.get('remove_path', 'local_path')
transport.close()

Class encapsulation

"""
我现在即想执行命令又想上传下载文件并且多次执行
yum install ansible
yum install redis
yum install redis
upload

单链接下完成多部操作
"""
# 下面写的类 你只要只要是想通过paramiko链接服务器都可以使用
import paramiko


class SSHProxy(object):
    def __init__(self, hostname, port, username, password):
        self.hostname = hostname
        self.port = port
        self.username = username
        self.password = password
        self.transport = None

    def open(self):  # 给对象赋值一个上传下载文件对象连接
        self.transport = paramiko.Transport((self.hostname, self.port))
        self.transport.connect(username=self.username, password=self.password)

    def command(self, cmd):  # 正常执行命令的连接  至此对象内容就既有执行命令的连接又有上传下载链接
        ssh = paramiko.SSHClient()
        ssh._transport = self.transport

        stdin, stdout, stderr = ssh.exec_command(cmd)
        result = stdout.read()
        return result

    def upload(self, local_path, remote_path):
        sftp = paramiko.SFTPClient.from_transport(self.transport)
        sftp.put(local_path, remote_path)
        sftp.close()

    def close(self):
        self.transport.close()

    def __enter__(self):  # 对象执行with上下文会自动触发
        # 
        # print('触发了enter')
        self.open()
        return self  # 这里发挥上面with语法内的as后面拿到的就是什么
        # return 123


    def __exit__(self, exc_type, exc_val, exc_tb):  # with执行结束自动触发
        # print('触发了exit')
        self.close()
"""
上面这个类在使用的时候 需要先执行open方法
obj = SSHProxy()
obj.open()  文件对象 链接服务器

obj.command()
obj.command()
obj.upload()
obj.upload()

obj.close()  关闭链接


文件操作
f = open()

f.write()
f.read()

f.close()

with上下文管理
with open() as f:
    ...
"""

# 对象默认是不支持with语法的   
# obj = SSHProxy('172.16.219.173',22,'root','jason123')
# with obj as f:
#     # print('进入with代码块')
#     print(f)
if __name__ == '__main__': 
    with SSHProxy('172.16.219.173',22,'root','jason123') as ssh:
        ssh.command()
        ssh.command()
        ssh.command()
        ssh.upload()

Object-oriented interview questions

"""
面试题
请在Context类中添加代码完成该类的实现
class Context:
    pass

with Context() as ctx:
    ctx.do_something()
"""
class Context:
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass
    
    def do_something(self):
        pass

with Context() as ctx:
    ctx.do_something()

Python operation git

installation

pip3 install gitpython

Basic use

from git.repo import Repo
import os


# 从远程仓库下载代码到本地   pull/clone
download_path = os.path.join('jason','NB')
# 从远程仓库将代码下载到上面创建的目录中
Repo.clone_from('https://github.com/DominicJi/TeachTest.git',to_path=download_path,branch='master')

More operations

# ############## 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("\n")
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)

Packaged version

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("\n")
        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()

to sum up

"""
后期你在接触一些模块的时候 也应该想到将该模块所有的方法整合到一起
方便以后的调用
"""

Guess you like

Origin www.cnblogs.com/fwzzz/p/12733962.html