###内容回顾
- crm
- 1.展示
- 1 普通的字段
- 对象.字段名
- 2 choice
- 对象.字段名 -> 数据库的值
- 对象.get_字段名_display
- 3 外键
- 对象.外键 ->关联的对象 定义__str__
- 对象.外键.字段名
- 4 多对多
- 给model类中自定义方法
```python
class Book(models.Model):
title = models.CharField(max_length=32)
category = models.IntegerField(choices=((1, '言情'), (2, '科幻')))
pub = models.ForeignKey('Publisher', on_delete=models.CASCADE)
authors = models.ManyToManyField('Author')
def show_authors(self):
return ' '.join([ i.name for i in self.authors.all()])
def show_pub(self):
return mark_safe("<a href='{}'>{}</a>".format(reverse('app01:edit_publisher', args=(self.pub_id,)), self.pub))
```
- 2 新增和编辑
- modelform
- 两个url + 一个视图函数 + 一个模板
```python
re_path(r'^user_add/$', user.User_change.as_view(), name='user_add'),
re_path(r'^user_edit/(d+)/$', user.User_change.as_view(), name='user_edit'),
```
```python
class User_change(View):
'''用户添加或编辑'''
def get(self, request, pk=None):
user_obj = models.User.objects.filter(pk=pk).first()
form_obj = UserForm(instance=user_obj)
title = '编辑用户' if pk else '添加用户'
return render(request, 'form.html', locals())
def post(self, request, pk=None):
user_obj = models.User.objects.filter(pk=pk).first()
form_obj = UserForm(data=request.POST, instance=user_obj)
if form_obj.is_valid():
form_obj.save()
url = request.GET.get('return_url')
if url:
return_url = url
else:
return_url = 'user_list'
return redirect(return_url)
title = '编辑用户' if pk else '添加用户'
return render(request, 'form.html', locals())
```
```html
{% extends 'layout.html' %}
{% block content %}
<div class="container-fluid" style="margin-top: 20px;">
<div class="col-md-12">
<div class="panel panel-info mystyle-panel">
<div class="panel-heading">
{{ title }}
</div>
<div class="panel-body">
<form class="form-horizontal" method="post" action="" novalidate>
{% for field in form_obj %}
{% csrf_token %}
<div class="form-group {% if field.errors %}has-error{% endif %}">
<label for="{{ field.id_for_label }}"
class="col-sm-2 control-label">{{ field.label }}</label>
<div class="col-sm-6">
{{ field }}
<span class="help-block">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-6">
<button type="submit" class="btn btn-default">保存</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
```
- 3 删除
```python
class User_del(View):
'''删除用户'''
def post(self, request, pk):
res = {'status': 1, 'msg': '删除失败'}
if models.User.objects.filter(pk=pk).delete():
res = {'status': 0, 'msg': '删除成功'}
return JsonResponse(res)
```
###今后的内容
- CMDB 配置管理数据库 资产的管理
- 自动化运维的平台:
- 1.监控
- 2.代码发布
- 开发cmdb
- 实现思路:
- 1.agent
- 1.每台机器都安装agent脚步
- 2.每天定期启动,执行命令获取硬件信息
- 3.把数据发送给api,由api进行入库
- 2.ssh
- 1.把agent脚步安装在中控机上
- 2.每天定期启动,通过ssh远程连接上被控机,执行命令获取硬件信息
- 3.把数据发送给api,由api进行入库
- 3.salt ansible 自动化运维的工具
- 1.把agent脚步安装在中控机上
- 2.每天定期启动,通过ssh远程连接上被控机,执行命令获取硬件信息
- 3.把数据发送给api,由api进行入库
兼容三种模式 + 可扩展
- 客户端auto_client
```python
# -*- coding: utf-8 -*-
import requests
import json
def run():
'''
执行命令采集信息
将采集到的信息发送给API
'''
info = {'cpu': {'cpu1': 'xxx', 'cpu2': 'xxxx'}, 'member': 'xxmemberxx'}
res = requests.post(
url='http://127.0.0.1:8000/api/asset/',
data=json.dumps(info).encode('utf-8')
)
print(res)
run()
```
- 服务端auto_server
- 路由表入口 auto_server/urls.py
```python
from django.contrib import admin
from django.urls import path, re_path, include
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^api/', include('api.urls'))
]
```
- 应用路由 api/urls.py
```python
from django.urls import re_path
from api import views
urlpatterns = [
re_path(r'^asset/$', views.Asset.as_view()),
]
```
- 视图函数 api/views.py
```python
from django.shortcuts import render, HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
import json
@method_decorator(csrf_exempt, name='dispatch')
class Asset(View):
'''
接收数据
保存数据到数据库
'''
def get(self, request):
return HttpResponse('ok1')
def post(self, request):
data_body = json.loads(request.body.decode('utf-8'))
return HttpResponse('ok2')
```
###错误信息的处理
```python
# -*- coding: utf-8 -*-
import traceback
def disk():
print('disk')
int('xx')
try:
disk()
except Exception:
print(traceback.format_exc())
```
###auto_client目录结构
- bin 启动文件
- client.py
```python
# -*- coding: utf-8 -*-
import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, BASE_DIR)
from src.script import run
if __name__ == '__main__':
'''启动文件'''
run()
```
- conf 配置文件
- settings.py
```python
# -*- coding: utf-8 -*-
ENGINE = 'agent' # agent ssh salt ansible
ENGINE_DICT = {
'agent': 'src.engine.agent.AgentHandler',
'ssh': 'src.engine.ssh.SshHandler',
'salt': 'src.engine.salt.SaltHandler',
'ansible': 'src.engine.ansible.AnsibleHandler',
}
PLUGINS_DICT = {
'disk': 'src.plugins.disk.Disk',
'memory': 'src.plugins.memory.Memory',
'nic': 'src.plugins.nic.NIC',
}
SSH_PORT = 22
SSH_USER = 'root'
SSH_PASSWORD = '123'
SSH_PRIVATE_KEY = ''
```
- lib 文件库
- import_class.py
```python
# -*- coding: utf-8 -*-
import importlib
def import_class(path):
path_str, class_str = path.rsplit('.', maxsplit=1)
module = importlib.import_module(path_str)
return getattr(module, class_str)
```
- log 日志文件
- src 业务逻辑
- engine 引擎
- agent.py
```python
# -*- coding: utf-8 -*-
from src.engine.base import BaseHandler
from src.plugins import get_server_info
class AgentHandler(BaseHandler):
def cmd(self, command, hostname=None):
import subprocess
ret = subprocess.getoutput(command)
return ret
def process(self):
'''
采集硬件资产信息 硬盘 内存 cpu 网卡 主板
把数据发送给API
:return:
'''
info = get_server_info(self)
print(info)
print('agent')
```
- ssh.py
- salt.py
- ansible.py
- base.py
```python
# -*- coding: utf-8 -*-
class BaseHandler():
def process(self):
raise NotImplementedError('process() must be implemented')
```
- plugins 插件
- __init__.py
```python
# -*- coding: utf-8 -*-
from lib.import_class import import_class
from conf import settings
def get_server_info(handler, hostname=None):
info = {}
for plugin_str, class_str in settings.PLUGINS_DICT.items():
cls = import_class(class_str)
if callable(cls):
obj = cls()
info[plugin_str] = obj.process(handler, hostname)
else:
print('{}文件中的{}类,不能被调用,请检查配置文件。'.format(__file__, cls))
return info
```
- base.py
```python
# -*- coding: utf-8 -*-
class BasePlugin():
def get_os(self, handler, hostname):
os = handler.cmd('uname -s', hostname)
if os == 'Linux':
return 'Linux'
else:
return 'win'
def process(self, handler, hostname):
os = self.get_os(handler, hostname)
if os == 'Linux':
return self.linux(handler, hostname)
else:
return self.win(handler, hostname)
```
- disk.py 硬盘信息
```python
# -*- coding: utf-8 -*-
from .base import BasePlugin
class Disk(BasePlugin):
def win(self, handler, hostname):
ret = handler.cmd('dir', hostname)
return ret[:10]
def linux(self, handler, hostname):
ret = handler.cmd('df', hostname)
return ret[:10]
```
- memory.py 内存信息
```python
# -*- coding: utf-8 -*-
from .base import BasePlugin
class Memory(BasePlugin):
def win(self, handler, hostname):
ret = handler.cmd('memory', hostname)
return ret[:10]
def linux(self, handler, hostname):
ret = handler.cmd('memory', hostname)
return ret[:10]
```
- nic.py 网卡信息
```python
# -*- coding: utf-8 -*-
from .base import BasePlugin
class NIC(BasePlugin):
def win(self, handler, hostname):
ret = handler.cmd('ipconfig', hostname)
return ret[:10]
def linux(self, handler, hostname):
ret = handler.cmd('ifconfig', hostname)
return ret[:10]
```
- script.py
```python
# -*- coding: utf-8 -*-
from conf import settings
from lib.import_class import import_class
def run():
'''业务逻辑'''
cls = import_class(settings.ENGINE_DICT.get(settings.ENGINE))
if callable(cls):
obj = cls()
obj.process()
else:
print('{}文件中的{}类,不能被调用,请检查配置文件。'.format(__file__, cls))
```
###约束类(抽象类+抽象方法)
```python
# -*- coding: utf-8 -*-
import abc
class Person(metaclass=abc.ABCMeta):
@abc.abstractmethod
def talk(self):
print('talk')
class Chinese(Person):
pass
p = Chinese()
```
###约束类(抛出异常)
```python
# -*- coding: utf-8 -*-
class Person():
def talk(self):
raise NotImplementedError('talk() must be implemented')
class Chinese():
pass
p = Chinese()
```