2019-01-16

CMDB增删改查(基于form表单)

1. 设计表,在models中定义好字段

  • models.py
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):
    '''主机,阿里云eth0 内网网卡, eth1 公网网卡'''
    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')
    lab= models.ForeignKey(to='Lable',blank=True, null=True, verbose_name='标签')
    mem= models.CharField(max_length=8,blank=True, null=True, verbose_name='内存/M')
    # mem= models.ForeignKey(to='Memory',blank=True, null=True, verbose_name='内存/M')
    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='磁盘')
    eth1_network= models.CharField(max_length=32, blank=True, null=True, verbose_name='公网IP')
    eth0_network= models.CharField(max_length=32,verbose_name='私网IP')
    sn= models.CharField(max_length=64, blank=True, null=True, verbose_name='sn')
    os= models.ForeignKey(to='Os', blank=True, null=True, verbose_name='操作系统') #os+版本号
    kernel= models.CharField(max_length=64, blank=True, null=True, verbose_name='系统内核') #内核+版本号
    the_upper=models.ForeignKey(to='Host',blank=True,null=True,verbose_name='宿主机',related_name='upper')
    source=models.ForeignKey(to='Source',blank=True,null=True,verbose_name='来源类型')
    region=models.ForeignKey(to='Region',blank=True,null=True,verbose_name='所属区域')
    remarks = models.CharField(max_length=2048, blank=True, null=True, verbose_name='备注')
    createtime = models.CharField(max_length=32, blank=True, null=True, verbose_name='创建时间')
    expirytime = models.CharField(max_length=32, blank=True, null=True, verbose_name='到期时间')
    vpcnet = models.ForeignKey(to='VpcNet', blank=True, null=True, verbose_name='VPC网络',related_name='vpcnet')
    vpcsw = models.ForeignKey(to='VpcSwitch', blank=True, null=True, verbose_name='VPC交换机')
    vpccon = models.ForeignKey(to='VpcNet', blank=True, null=True, verbose_name='VPC连接',related_name='vpccon')
    state_choices=(
        (1,'Running'),
        (2,'下线'),
        (3,'关机'),
        (4,'删除'),
    )
    state = models.SmallIntegerField(verbose_name='主机状态', choices=state_choices,blank=True,null=True,)
    def __str__(self):
        return self.eth0_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

2. 设计路由,增删改查分别走路径

  • 这里我们让增删改查走一个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')),
]
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()),
]

3. 利用Form表单来在前端展现数据:

  • 这里我们创建一个跟应用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')

4. 我们在apiAPP里面的viwe.py里面写增删改查逻辑

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')

5. 编写tempates中的html,用于前端展示

  • 其中我们需要一个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>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 一、简介 Influxdb是一个时序数据库(Time Series Database),适合保存按照时间顺序打点的...
    四火流年阅读 1,023评论 0 0
  • 12.4.2 IE8及更早版本中的范围 顾名思义,文本范围处理的主要是文本(不一定是DOM节点)。通过 等这...
    kathyever阅读 275评论 0 0
  • 前端部分 1. HTML、css、JavaScript在网页开发中的定位 HTML超文本标记语言,定义网页结构 c...
    Ernest_Chou阅读 199评论 0 0
  • 2018年12月1日,因为参加一次沙龙活动,认识了一位程序员张洪岩。因为当时的工作原因,需要学习一些IT行业的基础...
    央米阅读 166评论 0 0
  • 颓废的我认为,年轻人的生活是从下午开始的。 很久没有对别人说也很久没听到别人对我说:“早上好”。我的生活很乱,...
    鸡汤青年大叔阅读 234评论 0 0