初步实现cmdb增删改查功能,先实现功能后面补充样式。
class Disk(models.Model): '''磁盘''' path = models.CharField(max_length=64, blank=True, null=True, verbose_name='挂载路径') size = models.CharField(max_length=16, blank=True, null=True, verbose_name='磁盘大小/G') remarks = models.CharField(max_length=2048, blank=True, null=True, verbose_name='备注') def __str__(self): return self.size class Meta: verbose_name_plural = "磁盘表" class Region(models.Model): name = models.CharField(max_length=64,blank=True,null=True,verbose_name='区域') def __str__(self): return self.name class Meta: verbose_name_plural = "区域表" class Host(models.Model): hostname = models.CharField(max_length=64, blank=True, null=True, verbose_name='阿里云主机名') ecsname = models.CharField(max_length=64, blank=True, null=True, verbose_name='阿里云实例ID') logining = models.ManyToManyField(to='Login', blank=True, null=True, verbose_name='授权用户') login_port = models.CharField(max_length=16, default='22', blank=True, null=True, verbose_name='ssh登录端口') cpu = models.CharField(max_length=8, blank=True, null=True, verbose_name='CPU') mem = models.CharField(max_length=8, blank=True, null=True, verbose_name='内存/G') speed = models.CharField(max_length=8, blank=True, default='5', null=True, verbose_name='带宽/M') disks = models.ManyToManyField(to='Disk', blank=True, null=True, verbose_name='磁盘') network = models.CharField(max_length=32, blank=True, null=True, verbose_name='IP') sn = models.CharField(max_length=64, blank=True, null=True, verbose_name='sn') kernel = models.CharField(max_length=64, blank=True, null=True, verbose_name='系统内核') # 内核+版本号 source = models.ForeignKey(to='Source', blank=True, null=True, verbose_name='来源类型') region = models.ForeignKey(to='Region', blank=True, null=True, verbose_name='所属区域') state_choices = ( (1, 'Running'), (2, '下线'), (3, '关机'), (4, '删除'), (5, '故障'), ) state = models.SmallIntegerField(verbose_name='主机状态', choices=state_choices, blank=True, null=True, ) def __str__(self): return self.network class Meta: verbose_name_plural = "主机表" class Login(models.Model): '''登录相关''' login_name = models.CharField(max_length=16, default='root', verbose_name='登录用户名') login_pwd= models.CharField(max_length=64, blank=True, null=True, verbose_name='登录密码') auth=models.CharField(max_length=8,blank=True, null=True, verbose_name='具有权限') def __str__(self): return self.login_name class Meta: verbose_name_plural = "主机用户表" class Source(models.Model): '''来源:阿里云、物理机(某机房等)''' name = models.CharField(max_length=16, blank=True, null=True, verbose_name='来源') def __str__(self): return self.name class Meta: verbose_name_plural = "主机来源表"
初始化表,让其在数据库中创建对应的表:
python manage.py makemigrations python manage.py migrate
这里我们让增删改查走一个app,所以使用include引入:
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include('apiAPP.urls')), ]
新建一个apiAPP,然后新建一个urls.py,我们将其子路由定义在此。
from django.conf.urls import url,include from django.contrib import admin from apiAPP import views '''任何usl都会从这里匹配''' '''此处是精确匹配,写list.html,浏览器也要写list.html,后面带/的话,浏览器也要带/''' urlpatterns = [ url(r'^list$', views.List.as_view()), url(r'^update/(\d+)/', views.Update.as_view()), url(r'^add$', views.Add.as_view()), url(r'^del', views.Del.as_view()), ]
这里我们创建一个跟应用app同级的目录,utils,并且创建
form_class.py:
#!/usr/bin/python # -*- coding:utf-8 -*- # @Time : 2019/1/16 14:33 # @Author : liaochao # @File : form_class.py from django.forms import Form from django.forms import fields from django.forms import widgets from apiAPP import models class HostForm(Form): hostname = fields.CharField( required=True, #error_messages={'required': '不能为空'}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) cpu = fields.IntegerField( required=True, #error_messages={'required': '不能为空'}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) mem = fields.IntegerField( required=True, #error_messages={'required': '不能为空'}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) speed = fields.CharField( required=True, #error_messages={'required': '不能为空'}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) eth0_network = fields.CharField( required=True, #error_messages={'required': '不能为空'}, widget=widgets.TextInput(attrs={'class': 'form-control'}) ) # state = fields.ChoiceField( # required=True, # # values_list('id','name') 会让数据变成[(id,name),(id,name)] 这种格式 # choices=[], # #下拉框 # widget=widgets.Select(attrs={'class': 'form-control'}), # ) source_id = fields.ChoiceField( required=True, # values_list('id','name') 会让数据变成[(id,name),(id,name)] 这种格式 choices=[], #下拉框 widget=widgets.Select(attrs={'class': 'form-control'}), ) region_id = fields.ChoiceField( required=True, choices=[], widget=widgets.Select(attrs={'class': 'form-control'}) ) def __init__(self,*args,**kwargs): '每次都默认执行初始化,保证在数据库拿到的数据是最新的' super(HostForm,self).__init__(*args,**kwargs) # values_list('id','name') 会让数据变成[(id,name),(id,name)] 这种格式 self.fields['source_id'].choices = models.Source.objects.values_list('id','name') self.fields['region_id'].choices=models.Region.objects.values_list('id','name') # self.fields['state'].choices=models.Host.objects.values_list('id','state')
from django.shortcuts import render,HttpResponse,redirect from apiAPP import models from django.views import View from django.forms import Form from django.forms import fields from django.forms import widgets from utils import form_class # Create your views here. class List(View): def post(self,request,*args,**kwargs): pass def get(self,request,*args,**kwargs): # return HttpResponse('List') host_list=models.Host.objects.all() return render(request,'host.html',locals()) class Add(View): '''基于form的增加''' def post(self,request,*args,**kwargs): form =form_class.HostForm(data=request.POST) if form.is_valid(): print(form.cleaned_data) models.Host.objects.create(**form.cleaned_data) print("正常提交") return redirect('/api/list') else: print(form.errors) return render(request,'add.html',locals()) def get(self,request,*args,**kwargs): form = form_class.HostForm() return render(request,'add.html',locals()) class Update(View): '''基于form的修改''' def post(self,request,pk): print("post--id-->", pk) form = form_class.HostForm(data=request.POST) if form.is_valid(): print(form.cleaned_data) models.Host.objects.filter(id=pk).update(**form.cleaned_data) return redirect('/api/list') else: print(form.errors) return render(request,'edit.html',locals()) def get(self,request,pk): print ("get--id-->",pk) # # 拿到前端传过来的id # get_id = request.GET.get('id') obj = models.Host.objects.filter(id=pk).first() print(obj) form = form_class.HostForm( initial={ 'hostname':obj.hostname, 'cpu':obj.cpu, 'mem':obj.mem, 'speed':obj.speed, 'eth0_network':obj.eth0_network, 'source_id':obj.source_id, 'region_id':obj.region_id, # 'get_state_display ':obj.get_state_display , } ) # return HttpResponse('update') return render(request,'edit.html',locals()) class Del(View): def post(self,request,*args,**kwargs): pass def get(self,request,*args,**kwargs): get_id = int(request.GET.get('id')) models.Host.objects.filter(id=get_id).delete() return redirect('/api/list')
其中我们需要一个list展示的host.html,增加的add.html,编辑的edit.html。
host.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主机列表</title> </head> <body> <div> <a href="/api/add">添加</a> </div> <div class="container"> <table class="table table-bordered table-hover" id="table"> <thead> <tr> <th> </th> <th>主机名</th> <th>CPU</th> <th>内存/G</th> <th>带宽/M</th> <th>IP</th> <th>来源类型</th> <th>所属区域</th> <th>状态</th> <th>编辑</th> <th>删除</th> </tr> </thead> <tbody> {% for host in host_list %} <tr> <td>{{ host.id }}</td> <td>{{ host.hostname }}</td> <td>{{ host.cpu }}</td> <td>{{ host.mem }}</td> <td>{{ host.speed }}</td> <td>{{ host.eth0_network }}</td> <td>{{ host.source.name }}</td> <td>{{ host.region.name }}</td> <td>{{ host.get_state_display }}</td> <td><a href="/api/update/{{ host.id }}">编辑</a></td> <td><a href="/api/del?id={{ host.id }}">删除</a></td> </tr> {% endfor %} </tbody> </table> </div> </body> </html>
add.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主机添加</title> </head> <body> <form class="form-horisontal templatemo-container templatemo-login-form-1 margin-bottom-30" method="post" novalidate role="form"> {% csrf_token %} <p id="hostname">主机名:{{ form.hostname }} {{form.errors.hostname.0 }}</p> <p id="cpu">cpu:{{ form.cpu }} {{ form.errors.cpu.0 }}</p> <p id="mem">内存:{{ form.mem }} {{ form.errors.mem.0 }}</p> <p id="speed">带宽:{{ form.speed }} {{ form.errors.speed.0 }}</p> <p id="eth0_network">网卡ip:{{ form.eth0_network }} {{ form.errors.eth0_network }}</p> <p id="source.name">来源:{{ form.source_id }}</p> <p id="region.name">区域:{{ form.region_id }}</p> <input type="submit" value="提交"> </form> </body> </html>
edit.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>数据编辑</title> </head> <body> <form class="form-horisontal templatemo-container templatemo-login-form-1 margin-bottom-30" method="post" novalidate role="form"> {% csrf_token %} <p id="hostname">主机名:{{ form.hostname }} {{form.errors.hostname.0 }}</p> <p id="cpu">cpu:{{ form.cpu }} {{ form.errors.cpu.0 }}</p> <p id="mem">内存:{{ form.mem }} {{ form.errors.mem.0 }}</p> <p id="speed">带宽:{{ form.speed }} {{ form.errors.speed.0 }}</p> <p id="eth0_network">网卡ip:{{ form.eth0_network }} {{ form.errors.eth0_network }}</p> <p id="source.name">来源:{{ form.source_id }}</p> <p id="region.name">区域:{{ form.region_id }}</p> <input type="submit" value="提交"> </body> </html>
访问List页面:
http://127.0.0.1:8000/api/list
点击添加:http://127.0.0.1:8000/api/add
点击修改跟添加类似,只是会默认取到这行数据的id,然后把数据全部填充进去。 点击删除会删除选中数据。