首页 » Python » python3 高级篇 » 正文

CMDB_基础模型(增删改查)

一、写在前面:

先排除样式,主要是看代码逻辑!基于django_form!

1.1、设计表,在models中定义好字段;

models.py

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models
from django import forms
# Create your models here.

##采用models方式创建一个 <资产管理> 数据库表和字段

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 = "主机来源表"

1.2、创建对应的表:

python manage.py makemigrations  
python manage.py migrate

并创建一个superuser
python manage.py createsuperuser

1.3、当然为了方便,我们可以登入后台管理界面添加:

地址:http://127.0.0.1:8000/admin/

数据注册:

admin.py

# Register your models here.

from django.contrib import admin
from host import models


class host(admin.ModelAdmin):
    list_display = ['hostname', 'ecsname', 'cpu', 'mem', 'network', 'source', 'region', 'state']

class Disk(admin.ModelAdmin):
    list_display = ['path', 'size', 'remarks']

class Region(admin.ModelAdmin):
    list_display = ['name']

class Login(admin.ModelAdmin):
    list_display = ['login_name', 'auth']

class Source(admin.ModelAdmin):
    list_display = ['name']

admin.site.register(models.Host, host)
admin.site.register(models.Disk, Disk)
admin.site.register(models.Region, Region)
admin.site.register(models.Login, Login)
admin.site.register(models.Source, Source)

mark

二、设计路由

2.1、创建了我们的应用,就需要引用我们应用中urls.py(自己创建!)

from django.contrib import admin
from django.conf.urls import url,include

urlpatterns = [
    url('admin/', admin.site.urls),
    url(r'^host/', include('host.urls')),
]

2.2、新建一个host,然后新建一个urls.py

from django.conf.urls import url,include
from django.contrib import admin
from host import views

urlpatterns = [
    url(r'list$', views.List.as_view()),
    url(r'edit/(\d+)/', views.Update.as_view()),
    url(r'add$', views.Add.as_view()),
    url(r'del', views.Del.as_view()),
]

2.3、利用Form表单来在前端展现数据:

这里我们创建一个跟应用app同级的目录,utils,并且创建 form_class.py:

from django.forms import fields
from django.forms import widgets
from django.forms import Form
from host import models

class HostForm(Form):
	hostname = fields.CharField(
		required=True,      #规定该字段不能为空
		# error_messages={'required': '不可以为空'},
		widget=widgets.TextInput(attrs={'class': 'form-control'})
	)

	ecsname = fields.CharField(
		required=True,
		# error_messages = {'required': '不可以为空'},
		widget = widgets.TextInput(attrs={'class': 'form-control'})
	)

	cpu = fields.CharField(
		required=True,
		# error_messages = {'required': '不可以为空', 'invalid':'输入不合法'},
		widget = widgets.TextInput(attrs={'class': 'form-control'})
	)

	mem = fields.CharField(
		required=True,
		# error_messages = {'required': '不可以为空', 'invalid':'输入不合法'},
		widget = widgets.TextInput(attrs={'class': 'form-control'})
	)

	speed = fields.CharField(
		required=True,
		# error_messages = {'required': '不可以为空', 'invalid':'输入不合法'},
		widget = widgets.TextInput(attrs={'class': 'form-control'})
	)

	network = fields.CharField(
		required=True,
		# error_messages = {'required': '不可以为空', 'invalid':'输入不合法'},
		widget = widgets.TextInput(attrs={'class': 'form-control'})
	)

	source_id = fields.ChoiceField(
		required=True,
		# error_messages = {'required': '不可以为空', 'invalid':'输入不合法'},
		choices=[],     ##下拉框
		widget = widgets.Select(attrs={'class': 'form-control'})
	)

	region_id = fields.ChoiceField(
		required=True,
		# error_messages = {'required': '不可以为空', 'invalid':'输入不合法'},
		choices=[],
		widget = widgets.Select(attrs={'class': 'form-control'})
	)

	def __init__(self, *args, **kwargs):      ##每次都默认执行初始化,保证在数据库拿到的数据是最新的;
		super(HostForm, self).__init__(*args, **kwargs)
		self.fields['source_id'].choices=models.Source.objects.values_list('id', 'name')
		self.fields['region_id'].choices=models.Region.objects.values_list('id', 'name')

注解:

每个字段默认就是required=True;

字段没有自定义error_messages的值时,默认值是英文的错误提示;自定义的error_messages值中可以有多个错误信息提示,"required"是在该字段为空是提示,"invalid"是在该字段有值,但是值无效时提示,如邮箱或IP地址不对;

widgets插件,给Form生成的标签添加class等属性

三、增删改查

views.py

from django.shortcuts import render, HttpResponse, redirect
from host 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):
		host_list = models.Host.objects.all()
		return render(request, 'host.html', locals())


class Add(View):
	def post(self, request, *args, **kwargs):
		form = form_class.HostForm(data=request.POST)
		# print(request.POST)
		if form.is_valid():
			print(form.cleaned_data)
			models.Host.objects.create(**form.cleaned_data)
			return redirect('/host/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 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('/host/list')


class Update(View):

	def post(self, request, pk):    ##request 后面的值 pk  url传入的值,类似于 ->url  host.id 
		# print(pk)
		form = form_class.HostForm(data=request.POST)      # 将前端获取的数据传入到forms.UserForm类,实例化得到一个包含字段值的表单对象form
		if form.is_valid():      ##is_valid()得到一个布尔值,即判断传入的字段值是否全部有效
			print(form.cleaned_data)
			models.Host.objects.filter(id=pk).update(**form.cleaned_data)    ##直接插入数据库,form字段必须与models中定义的一致
			return redirect('/host/list')
		else:
			print(form.errors)
			return render(request, 'edit.html', locals())

	def get(self, request, pk):
		# get_id = request.GET.get('id')
		obj = models.Host.objects.filter(id=pk).first()
		form = form_class.HostForm(
			initial={
				'hostname': obj.hostname,
				'ecsname': obj.ecsname,
				'cpu': obj.cpu,
				'mem': obj.mem,
				'speed': obj.speed,
				'network': obj.network,
				'source_id': obj.source_id,
				'region_id': obj.region_id,
			}
		)
		return render(request, 'edit.html', locals())

注解:

form.is_valid()方法得到一个布尔值,判断从前端得到表单数据是全部有效;

form.cleaned_data得到全部验证有效的数据,是一个字典类型,如:{'username': 'admin', 'ip': '1.1.1.1', 'usertype_id': '3', 'email': '555@qq.com', 'password': 'admin'},字典中的key对应UserForm类中的每个字段名;

form.errors验证有误的错误提示信息,与错误字段一一对应,如:form.errors.user可以得到user字段的全部错误信息,是一个列表类型,form.errors.user[0]得到user字段的第一个错误信息。form.errors.email[0]得到email字段的第一个错误信息;

四、前端展示

host.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主机</title>
</head>
<body>

 <div class="container">
        <table class="table table-bordered table-hover" id="table" border="1">
            <thead>
            <tr>
                <th style="text-align: center"> </th>
                <th style="text-align: center">主机名</th>
                <th style="text-align: center">实例ID</th>
                <th style="text-align: center">CPU</th>
                <th style="text-align: center">内存/G</th>
                <th style="text-align: center">带宽/M</th>
                <th style="text-align: center">IP</th>
                <th style="text-align: center">来源类型</th>
                <th style="text-align: center">所属区域</th>
                <th style="text-align: center">状态</th>
                <th style="text-align: center"> </th>
            </tr>
            </thead>

            <tbody>
            {% for host in host_list %}
                <tr>
                    <td style="text-align: center">{{ forloop.counter }}</td>
                    <td style="text-align: center">{{ host.hostname }}</td>
                    <td style="text-align: center">{{ host.ecsname }}</td>
                    <td style="text-align: center">{{ host.cpu }}</td>
                    <td style="text-align: center">{{ host.mem }}</td>
                    <td style="text-align: center">{{ host.speed }}</td>
{#                    <td style="text-align: center"><a href="/search/?mem={{ item.mem_info }}">{{ item.mem_info }}</a>#}
{#                    </td>#}
                    <td style="text-align: center">{{ host.network }}</td>
                    <td style="text-align: center">{{ host.source.name }}</td>
                    <td style="text-align: center">{{ host.region.name }}</td>
                    <td style="text-align: center">{{ host.get_state_display }}</td>
                    <td style="text-align: center">
                        <a href="/host/del?id={{ host.id }}">删除</a> | <!--a标签是GET请求-->
                        <a href="/host/edit/{{ host.id }}">编辑</a> |
                        <a href="/host/add">增加</a>
                    </td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
</body>
</html>

add.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ADD</title>
</head>
<body>


<form class="form-horizontal" method="post" novalidate role="form">
    {% csrf_token %}
    <p id="hostname">阿里云主机:{{ form.hostname }} {{ form.errors.hostname.0 }}</p>
    <p id="ecsname">阿里云实例id{{ form.ecsname }} {{ form.errors.ecsname.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">带宽/M{{ form.speed }} {{ form.errors.speed.0 }}</p>
    <p id="network">IP{{ form.network }} {{ form.errors.network.0 }}</p>
    <p id="source">来源类型:{{ form.source_id }} {{ form.errors.source_id.0 }}</p>
    <p id="region">所属区域:{{ form.region_id }} {{ form.errors.region_id.0 }}</p>

    <input type="submit" value=" ">

</form>

</body>
</html>

edit.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form class="form-horizontal" method="post" novalidate role="form">
    {% csrf_token %}
    <p id="hostname">阿里云主机:{{ form.hostname }} {{ form.errors.hostname.0 }}</p>
    <p id="ecsname">阿里云实例id{{ form.ecsname }} {{ form.errors.ecsname.0 }}</p>
    <p id="cpu">CPU{{ form.cpu }}</p>
    <p id="mem">内存:{{ form.mem }}</p>
    <p id="speed">带宽/M{{ form.speed }}</p>
    <p id="network">IP{{ form.network }}</p>
    <p id="source">来源类型:{{ form.source_id }}</p>
    <p id="region">所属区域:{{ form.region_id }}</p>

    <input type="submit" value=" ">

</form>
</body>
</html>

五、前端展示测试:

数据库中数据展示:

mark

增加数据:

mark

修改:

mark

赞 (4)

发表评论