千家信息网

Django之入门 CMDB系统 (四) 增删改查

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,Django之入门 CMDB系统 (四) 增删改查前言作者: 何全,github地址: https://github.com/hequan2017 QQ交流群: 620176501通过此教程完成从零入
千家信息网最后更新 2025年01月23日Django之入门 CMDB系统 (四) 增删改查

Django之入门 CMDB系统 (四) 增删改查


前言

作者: 何全,github地址: https://github.com/hequan2017 QQ交流群: 620176501

通过此教程完成从零入门,能够独立编写一个简单的CMDB系统。

目前主流的方法开发方式,分为2种:mvc 和 mvvc方式。本教程为 mvc 方式,即 django负责渲染html。后面会推出 mvvc(前后端分离)的入门教程。

教程项目地址: https://github.com/hequan2017/husky/

教程文档地址: https://github.com/hequan2017/husky/tree/master/doc

说明

  • cbv 在视图里使用类处理请求 (下面采用这种方式,比较会抽象一点,但是会比较简洁)
  • fbv 在视图里使用函数处理请求

基础设置

pycharm : 菜单栏 tools --> 选择 run manage.py task

manage.py@husky > startapp asset ##创建 asset app

具体内容请看实际页面,下面只是把重点代码 进行展示。

  • settings.py 增加系统配置
import sysINSTALLED_APPS = [    "asset",]
  • asset/modes.py
from django.db import modelsclass Ecs(models.Model):    TYPE_CHOICES = (        ('阿里云', '阿里云'),        ('腾讯云', '腾讯云'),        ('华为云', '华为云'),        ('亚马逊', '亚马逊'),        ('其他', '其他'),        (None,None),    )    hostname = models.CharField(max_length=96, verbose_name='主机名', blank=True, null=True, )    type = models.CharField(choices=TYPE_CHOICES, max_length=16, verbose_name='主机类型', blank=True, null=True, )    instance_id = models.CharField(max_length=64, verbose_name='实例ID', unique=True)    instance_name = models.CharField(max_length=96, verbose_name='标签', blank=True, null=True, )    os_name = models.CharField(max_length=64, verbose_name='系统版本', blank=True, null=True, )    cpu = models.IntegerField(verbose_name='CPU', blank=True, null=True)    memory = models.IntegerField(verbose_name='内存', blank=True, null=True)    private_ip = models.GenericIPAddressField(verbose_name='内网IP', blank=True, null=True)    public_ip = models.GenericIPAddressField(verbose_name='外网IP', blank=True, null=True)    c_time = models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间', blank=True)    u_time = models.DateTimeField(auto_now=True, null=True, verbose_name='更新时间', blank=True)    class Meta:        db_table = "ecs"        verbose_name = "主机"        verbose_name_plural = verbose_name    def __str__(self):        return self.hostname

pycharm : 菜单栏 tools --> 选择 run manage.py task

makemigrations 生成数据文件

migrate 根据文件,执行生成表结构

  • asset/form.py
from django import formsfrom asset.models import Ecsclass EcsForm(forms.ModelForm):    class Meta:        model = Ecs        fields = '__all__'        widgets = {            'type': forms.Select(                attrs={'class': 'select2',                       'data-placeholder': '----请选择环境----'}),        }        help_texts = {            'type': '* 请选择 资产所在平台.',        }    def clean_type(self):        """        自定义验证        :return:        """        type = self.cleaned_data['type']        return type
  • asset/admin.py
from django.contrib import adminfrom asset.models import Ecsadmin.site.register(Ecs)
  • 自定义标签处理
    • asset/templatetags/asset_filter.py
from django import templatefrom django.apps import appsfrom asset.models import Ecsregister = template.Library()@register.filter(name='ecs_model_choices')def ecs_model_choices(model_name, choice_name):    asset_app = apps.get_app_config('assets')    return getattr(asset_app.get_model(model_name), choice_name)@register.filter(name='ecs_type_choices')def ecs_type_choices(value):    return  Ecs.TYPE_CHOICES

增加

  • asset/views.py
class EcsCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):    """    Ecs 创建    """    permission_required = ('asset.add_ecs',)    model = Ecs    form_class = EcsForm    template_name = 'asset/ecs-create.html'    success_url = reverse_lazy('asset:ecs-list')    def get_context_data(self, **kwargs):        context = {}        if '__next__' in self.request.POST:  # 为了获取 点击本页之前的 浏览网页            context['i__next__'] = self.request.POST['__next__']        else:            try:                context['i__next__'] = self.request.META['HTTP_REFERER']            except Exception as e:                logger.error(e)        kwargs.update(context)        return super().get_context_data(**kwargs)    def get_success_url(self):        return self.request.POST['__next__']    def form_valid(self, form):  #  保存结果 可以进行 手动 修改 再保存        obj = form.save(commit=False)        obj.save()        return super().form_valid(form)    def form_invalid(self, form):        print(form.errors)        """If the form is invalid, render the invalid form."""        return self.render_to_response(self.get_context_data(form=form))
  • asset/urls.py
from django.urls import pathfrom asset import viewsapp_name = "asset"urlpatterns = [    path('ecs-create', views.EcsCreateView.as_view(), name='ecs-create')]
  • templates/base/_js.html
  • templates/base/_nav.html
                
  • templates/asset/ecs-create.html
    
{% csrf_token %} {% if form.non_field_errors %}
{{ form.non_field_errors }}
{% endif %}

基本

{% bootstrap_field form.hostname layout="horizontal" %} {% bootstrap_field form.type layout="horizontal" %} {% bootstrap_field form.instance_id layout="horizontal" %} {% bootstrap_field form.instance_name layout="horizontal" %} {% bootstrap_field form.os_name layout="horizontal" %} {% bootstrap_field form.cpu layout="horizontal" %} {% bootstrap_field form.memory layout="horizontal" %} {% bootstrap_field form.private_ip layout="horizontal" %} {% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_button "保存" button_type="submit" button_class="btn-primary" %} 取消
{% block footer-js %} {% endblock %}

列表

  • asset/views.py
def get_list(function):    """    列表页面  获取 搜索    :param function: self.model    :return:    """    @wraps(function)    def wrapped(self):        # user = self.request.user        # groups = [x['name'] for x in self.request.user.groups.values()]        # request_type = self.request.method        # model = str(self.model._meta).split(".")[1]        filter_dict = {}        not_list = ['page', 'order_by', 'csrfmiddlewaretoken']        for k, v in dict(self.request.GET).items():            if [i for i in v if i != ''] and (k not in not_list):                if '__in' in k:                    filter_dict[k] = v                else:                    filter_dict[k] = v[0]        self.filter_dict = filter_dict        self.queryset = self.model.objects.filter(**filter_dict).order_by('-id')        order_by_val = self.request.GET.get('order_by', '')        if order_by_val:            self.queryset = self.queryset.order_by(order_by_val) if self.queryset else self.queryset        result = function(self)        return result    return wrappedclass EcsListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):    permission_required = ('asset.view_ecs',)    template_name = 'asset/ecs-list.html'    model = Ecs    queryset = Ecs.objects.get_queryset().order_by('-id')    @get_list  ## 处理查询    def get_context_data(self, **kwargs):        try:            page = self.request.GET.get('page', 1)        except PageNotAnInteger as e:            page = 1        p = Paginator(self.queryset, getattr(settings, 'DISPLAY_PER_PAGE'), request=self.request)        ecs_list = p.page(page)        context = {            "ecs_list": ecs_list,            "filter_dict": self.filter_dict  # 把查询条件返回给前端        }        kwargs.update(context)        return super().get_context_data(**kwargs)
  • asset/urls.py
path('ecs-list', views.EcsListView.as_view(), name='ecs-list'),
  • templates.py/asset/ecs-list.html
   
{% csrf_token %} {% for row in ecs_list.object_list %} {% endfor %}
主机名 主机类型 实例ID 标签 系统版本 内网IP 创建时间 操作
{{ row.hostname }}
{{ row.get_type_display }}
{{ row.instance_id }}
{{ row.instance_name }}
{{ row.os_name }}
{{ row.private_ip }}
{{ row.c_time | date:'Y-m-d' }}
{% if perms.asset.view_ecs %} 详情 {% endif %} {% if perms.asset.change_ecs %} 编辑 {% endif %} {% if perms.asset.delete_ecs %} 删除 {% endif %}
{% block footer-js %}

更新

  • asset/views.py
class EcsUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):    permission_required = ('asset.change_ecs',)    model = Ecs    form_class = EcsForm    template_name = 'asset/ecs-create.html'    success_url = reverse_lazy('asset:ecs-list')    def get_context_data(self, **kwargs):        context = {}        if '__next__' in self.request.POST:  # 为了获取 点击本页之前的 浏览网页            context['i__next__'] = self.request.POST['__next__']        else:            try:                context['i__next__'] = self.request.META['HTTP_REFERER']            except Exception as e:                logger.error(e)        kwargs.update(context)        return super().get_context_data(**kwargs)    def get_success_url(self):        return self.request.POST['__next__']
  • asset/urls.py
    path('ecs-update-', views.EcsUpdateView.as_view(), name='ecs-update'),
  • templates.py/asset/ecs-create.html 创建页面 同时也当更新页面
     {% if perms.asset.change_ecs %}        编辑    {% endif %}

删除

  • asset/views.py
class EcsDeleteView(LoginRequiredMixin, PermissionRequiredMixin, View):    permission_required = ('asset.delete_ecs',)    model = Ecs    def post(self, request):        ret = {'status': True, 'error': None, }        nid = self.request.POST.get('nid', None)        self.model.objects.get(id=nid).delete()        return HttpResponse(json.dumps(ret))
  • asset/urls.py

path('ecs-delete', views.EcsDeleteView.as_view(), name='ecs-delete'),

templates.py/asset/ecs-list.html

 {% if perms.asset.delete_ecs %} 删除  {% endif %}
   $(function () {                $_(document).on('click', '.ecs-delete', function () {                    var id = $(this).parent().parent().attr('id');                    var name = $(this).parent().parent().attr('name');                    swal({                        title: "你确定删除",                        text: name,                        type: "warning",                        showCancelButton: true,                        confirmButtonColor: "#DD6B55",                        confirmButtonText: "确定",                        cancelButtonText: "取消",                        closeOnConfirm: false                    }, function () {                        $.ajax({                            url: "{% url 'asset:ecs-delete' %}",                            type: 'POST',                            data: {'nid': id},                            success: function (data) {                                var obj = JSON.parse(data);                                if (obj.status) {                                    swal({title: "删除", text: "已成功删除", type: "success"}, function () {                                        _window.location.reload();                                    })                                } else {                                    swal("错误", "删除" + "[ " + obj.error + " ]" + "遇到错误", "error");                                }                            }                        });                    });                });            });

详情

  • asset/views.py
class EcsDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):    permission_required = ('asset.view_ecs',)    model = Ecs    form_class = EcsForm    template_name = 'asset/ecs-detail.html'    def get_context_data(self, **kwargs):        pk = self.kwargs.get(self.pk_url_kwarg, None)        context = {            "ecs": self.model.objects.get(id=pk),            "nid": pk        }        kwargs.update(context)        return super().get_context_data(**kwargs)
  • asset/urls.py

path('ecs-detail-', views.EcsDetailView.as_view(), name='ecs-detail'),

  • templates.py/asset/ecs-list.html
    
主机类型: {{ ecs.get_type_display }}
实例ID: {{ ecs.instance_id }}
标签: {{ ecs.instance_name }}
系统版本: {{ ecs.os_name }}
CPU: {{ ecs.cpu }}
内存: {{ ecs.memory }}
内网IP: {{ ecs.private_ip }}
外网IP: {{ ecs.public_ip }}
创建时间: {{ ecs.c_time }}
更新时间: {{ ecs.u_time }}
数据 系统 主机 教程 时间 页面 搜索 方式 标签 处理 更新 查询 选择 地址 实例 版本 类型 资产 上一 内存 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 如何建立高质量的客户数据库 深圳市金芒果软件开发有限公司 石嘴山app软件开发哪家专业 临沂商城软件开发哪家靠谱 数据库 求候选键方法 dnf提示网络安全掉线 星雅服务器 西城数据库安全审计系统 高新技术数据库 软件开发想要融资 盐城常规软件开发价格多少 国际服进入游戏服务器没有响应 税务局网络安全三字 应聘安卓软件开发的简历 日本服务器数据丢失感想 易安卓软件开发教程 陈威 网络安全 如何把数据库部署到本地服务器 电脑处于网络安全模式 合肥电动汽车热管理软件开发价格 哪些名人是学计算机网络技术专业 洛克王国服务器容量 青浦区进口软件开发质量保障 金蝶软件附加数据库 手机我的世界修仙服务器推荐 数据库中表和表的关系建立 宽带挂机服务器 飞马网络技术有限公司 迅雷bt链接无法连接到服务器 北京创新财富网络技术
0