Django运维后台的搭建之五:引入databases和django-crispy-forms

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django运维后台的搭建之五:引入databases和django-crispy-forms相关的知识,希望对你有一定的参考价值。

在上一篇,我们已经把我们做的运维外面套上了bootstrap框架,但是那仅仅是一个外壳,这一次是要把里面的壤也扣上这样的框架。


首先,编辑index.html,添加block元素,用于主页存放不同的内容:

<div class="page-content">  
   <div class="page-content-area">  
                    <div class="page-header">  
                            <h1>  
                                <!--设置导航栏的页面标题-->  
                                {% block page_title %}  
                                {% endblock %}  
                                <small>  
                                    <i class="ace-icon fa fa-angle-double-right"></i>  
                                     <!--设置导航栏的页面子标题-->  
                                    {{ sub_title }}  
                                </small>  
                            </h1>  
                        </div><!-- /.page-header -->  
      <div class="row">  
         <div class="col-xs-12">  
            <!-- PAGE CONTENT BEGINS -->  
                <!--设置页面内容-->  
                            {% block container %}  
                            {% endblock %}  
            <!-- PAGE CONTENT ENDS -->  
         </div><!-- /.col -->  
      </div><!-- /.row -->  
   </div><!-- /.page-content-area -->  
</div><!-- /.page-content -->


之前在models.py里我们设定了很多个项目,比如alionlineECS,alifuncECS等等,那么对应每一个项目都会有一个html,在这里我命名:alionlineECS_list.html用于存放“阿里云线上环境服务器”信息,alifuncECS_list.html用于“阿里云测试环境服务器”信息,ksonlineECS_list.html用于存放“金山云线上环境服务器”信息,ksfuncECS_list.html用于“金山云测试环境服务器”信息,同时修改index.html中Table下的链接,将其中的链接指向上面那些html们:

<ul class="submenu">  
   <li class="">  
      <a href="{% url ‘lists‘ table=‘alionlineECS‘ %}">  
         <i class="menu-icon fa fa-caret-right"></i>  
         阿里云线上环境服务器 
      </a>  
      <b class="arrow"></b>  
   </li>  
   <li class="">  
      <a href="{% url ‘lists‘ table=‘alifuncECS‘ %}">  
         <i class="menu-icon fa fa-caret-right"></i>  
         阿里云测试环境服务器  
      </a>  
      <b class="arrow"></b>  
   </li>  
    <li class="">  
      <a href="{% url ‘lists‘ table=‘ksonlineECS‘ %}">  
         <i class="menu-icon fa fa-caret-right"></i>  
         金山云线上环境服务器 
      </a>  
      <b class="arrow"></b>  
    <li class="">  
          <a href="{% url ‘lists‘ table=‘ksfuncECS‘ %}">  
             <i class="menu-icon fa fa-caret-right"></i>  
             金山云测试环境服务器 
      </a>  
      <b class="arrow"></b>   
   </li>  
</ul>

建立res_list.html放在之前的template文件夹里,用来存放资源类表格,并把它作为一个模板,供其他页面继承,这样可以节省大量的重复代码。

<!--继承index.html-->  
{% extends "index.html" %}  
{% block page_css %}  
{% endblock %}  
<!--填充导航栏的页面名称-->  
{% block page_title %}  
    基础资料  
{% endblock %}  
<!--放置主页面内容-->  
{% block container %}  
    {% load staticfiles %}  
    <div class="row">  
        <!-- Search Page BEGINS-->  
        <div class="col-xs-12">  
            <form class="navbar-for navbar-container" role="search" method="get" action="">{% csrf_token %}  
                <!--放置搜索栏内容-->  
                {% block search %}  
                {% endblock %}  
                <div class="col-sm-3">  
                        <span class="input-group-btn">  
                           <button type="submit" class="btn btn-purple btn-sm">  
                                        查询  
                                        <i class="ace-icon fa fa-search icon-on-right bigger-110"></i>  
                                    </button>  
                        </span>  
                </div>  
            </form>  
        </div>  
        <!-- Search Page END -->  
        <!-- PAGE TABLES BEGINS -->  
        <div class="col-xs-12">  
            <div>  
                <table id="table_id" class="table table-striped table-bordered table-hover">  
                    <thead>  
                    <!--表格头部-->  
                    {% block table_tr %}  
                    {% endblock %}  
                    <th>  
                        <!--最后一列作为添加数据按钮-->  
                        <a class="blue" href="{% url ‘add‘ table=table %}">  
                            <i class="ace-icon fa fa-search-plus bigger-130"></i>  
                            添加数据  
                        </a>  
                    </th>  
                    </thead>  
                   <!--表格内容-->  
                    <tbody>  
                    {% for item in data %}  
                        <tr>  
                            <!--通过for循环从data取出的具体表格内容-->  
                            {% block table_td %}  
                            {% endblock %}  
                            <td>  
                                <!--页面扩展时的按钮布局-->  
                                <div class="hidden-sm hidden-xs action-buttons">  
                                    <!--编辑信息按钮-->  
                                    <a class="green" href="{% url ‘edit‘ table item.id %}" title="编辑信息">  
                                        <i class="ace-icon fa fa-pencil bigger-130"></i>  
                                    </a>  
                                    <!--删除信息按钮-->  
                                    <a class="red" href="{% url ‘delete‘ table item.id %}" title="删除信息">  
                                        <i class="ace-icon fa fa-trash-o bigger-130"></i>  
                                    </a>  
                                </div>  
                                <!--页面收缩时的按钮布局-->  
                                <div class="hidden-md hidden-lg">  
                                    <div class="inline position-relative">  
                                        <button class="btn btn-minier btn-yellow dropdown-toggle" data-toggle="dropdown"  
                                                data-position="auto">  
                                            <i class="ace-icon fa fa-caret-down icon-only bigger-120"></i>  
  
                                        </button>  
  
  
                                        <ul class="dropdown-menu dropdown-only-icon dropdown-yellow dropdown-menu-right dropdown-caret dropdown-close">  
                                            <li>  
                                                <a href="{% url ‘add‘ table=table %}" class="tooltip-info" data-rel="tooltip" title="添加数据">  
                                                            <span class="blue">  
                                                               <i class="ace-icon fa fa-search-plus bigger-120"></i>  
                                                            </span>  
                                                </a>  
                                            </li>  
  
                                            <li>  
                                                <a href="{% url ‘edit‘ table item.id %}" class="tooltip-success" data-rel="tooltip" title="修改信息">  
                                                            <span class="green">  
                                                               <i class="ace-icon fa fa-pencil-square-o bigger-120"></i>  
                                                            </span>  
                                                </a>  
                                            </li>  
  
                                            <li>  
                                                <a href="{% url ‘delete‘ table item.id %}" class="tooltip-error" data-rel="tooltip" title="删除信息">  
                                                            <span class="red">  
                                                               <i class="ace-icon fa fa-trash-o bigger-120"></i>  
                                                            </span>  
                                                </a>  
                                            </li>  
                                        </ul>  
                                    </div>  
                                </div>  
                            </td>  
                        </tr>  
                    {% endfor %}  
                    </tbody>  
                </table>  
            </div>  
        </div>  
    </div>  
{% endblock %}  
{% block page_javascript %}  
    <!--datatable的专用js-->  
    <script type="text/javascript">  
        $(document).ready(function () {  
            $(‘#table_id‘).DataTable({  
                //分页配置  
                "paging": false,  
                //搜索配置  
                "searching": false,  
                "bInfo": false,  
                //列配置  
                "columnDefs": [{  
                    //只有最后一行不需要排序  
                    "orderable": false, "targets": -1  
                }]  
            });  
        });  
    </script>  
  
{% endblock %}


alionlineECS_list.html,alifuncECS_list.html,slb_list.html等html文件继承res_list.html,并将各自不一样的内容在相应的block中进行填充,比如alionlineECS_list.html就是下面的样子:

{% extends "res_list.html" %}
{% block search %}
{% endblock %}
{% block table_tr %}
<th>云服务器名称</th>
<th>云服务器类型</th>
<th>云服务器内网地址</th>
<th>云服务器外网地址</th>
<th>云服务器外网带宽</th>
<th>云服务器配置</th>
<th>备注</th>
<th>登记人</th>
{% endblock %}
{% block table_td %}
<td>{{ item.ecs_name }}</td>
<td>{{ item.ecs_type }}</td>
<td>{{ item.ecs_inip }}</td>
<td>{{ item.ecs_outip }}</td>
<td>{{ item.ecs_ipwidth }}</td>
<td>{{ item.ecs_spec }}</td>
<td>{{ item.ecs_remarks }}</td>
<td>{{ item.ecs_signer }}</td>
{% endblock %}


而slb_list.html就是这样:

{% extends "res_list.html" %}
{% block search %}
{% endblock %}
{% block table_tr %}
<th>负载均衡名称</th>
<th>网络类型</th>
<th>转发规则</th>
<th>ip地址</th>
<th>负载均衡协议</th>
<th>前端端口</th>
<th>后端端口</th>
<th>负载均衡协议</th>
<th>前端端口</th>
<th>后端端口</th>
<th>登记人</th>
<th>备注</th>
{% endblock %}
{% block table_td %}
<td>{{ item.slb_name }}</td>
<td>{{ item.slb_type }}</td>
<td>{{ item.slb_algorithm }}</td>
<td>{{ item.slb_ip }}</td>
<td>{{ item.slb_protocol }}</td>
<td>{{ item.slb_fport }}</td>
<td>{{ item.slb_bport }}</td>
<td>{{ item.slb_protocol2 }}</td>
<td>{{ item.slb_fport2 }}</td>
<td>{{ item.slb_bport2 }}</td>
<td>{{ item.slb_signer }}</td>
<td>{{ item.slb_remarks }}</td>
{% endblock %}


rds_list.html的代码如下:

{% extends "res_list.html" %}
{% block search %}
{% endblock %}
{% block table_tr %}
<th>数据库名称</th>
<th>数据库类型</th>
<th>mysql版本</th>
<th>数据库规格</th>
<th>备注</th>
<th>数据库地址</th>
<th>存储空间</th>
<th>登记人</th>
{% endblock %}
{% block table_td %}
<td>{{ item.rds_name }}</td>
<td>{{ item.rds_type }}</td>
<td>{{ item.rds_mysql }}</td>
<td>{{ item.rds_spec }}</td>
<td>{{ item.rds_remark }}</td>
<td>{{ item.rds_ip }}</td>
<td>{{ item.rds_status }}</td>
<td>{{ item.rds_signer }}</td>
{% endblock %}


网页代码都准备好了,再往下的内容是修改views.py,把lists那个函数改成这样:

def lists(request,table):
        #不同的需求跳到不同的界面
    if table == ‘alionlineECS‘:
        data = alionlineECS.objects.all()
        list_template = ‘alionlineECS_list.html‘
        sub_title = ‘阿里云线上环境服务器‘
    if table == ‘alifuncECS‘:
        data = alifuncECS.objects.all()
        list_template = ‘alifuncECS_list.html‘
        sub_title = ‘阿里云测试环境服务器‘
    if table == ‘ksonlineECS‘:
        data = ksonlineECS.objects.all()
        list_template = ‘ksonlineECS_list.html‘
        sub_title = ‘金山云线上环境服务器‘
    if table == ‘ksfuncECS‘:
        data = ksfuncECS.objects.all()
        list_template = ‘ksfuncECS_list.html‘
        sub_title = ‘金山云线上环境服务器‘
    if table == ‘SLB‘:
        data = SLB.objects.all()
        list_template = ‘slb_list.html‘
        sub_title = ‘负载均衡‘
    if table == ‘RDS‘:
        data = RDS.objects.all()
        list_template = ‘rds_list.html‘
        sub_title = ‘数据库‘
        #建立一个context,将值传递到对应的页面
    context = {
        ‘data‘: data,
        ‘table‘: table,
        ‘sub_title‘: sub_title,
    }
        #跳转到相应页面,并将具体的值传递过去
    return render(request,list_template,context)


add的函数应该是这样:

def add(request,table):
    #根据提交的请求不同,获取来自不同Form的表单数据
    if table == ‘alionlineECS‘:
        form =  alionlineForm(request.POST or None)
    if table == ‘alifuncECS‘:
        form =  alifuncForm(request.POST or None)
    if table == ‘ksonlineECS‘:
        form =  ksonlineForm(request.POST or None)
    if table == ‘ksfuncECS‘:
        form =  ksfuncForm(request.POST or None)
    if table == ‘SLB‘:
        form =  SLBForm(request.POST or None)
    if table == ‘RDS‘:
        form =  RDSForm(request.POST or None)
    #判断form是否有效
    if form.is_valid():
        #创建实例,需要做些数据处理,暂不做保存
        instance = form.save(commit=False)
        #将登录用户作为登记人
        if table == ‘alionlineECS‘:
                instance.ecs_signer = request.user
        if table == ‘alifuncECS‘:
                instance.ecs_signer = request.user
        if table == ‘ksonlineECS‘:
                instance.ecs_signer = request.user
        if table == ‘ksfuncECS‘:
                instance.ecs_signer = request.user
        if table == ‘SLB‘:
                instance.slb_signer = request.user
        if table == ‘RDS‘:
                instance.rds_signer = request.user
        #保存该实例
        instance.save()
        #跳转至列表页面  
        return redirect(‘lists‘,table=table)
    #创建context来集中处理需要传递到页面的数据 
    context = {
        ‘form‘: form,
        ‘table‘: table,
    }
    #如果没有有效提交,则仍留在原来页面  
    return render(request,‘add.html‘,context)


同时,我们要添加两个新的函数,一个叫edit,他的内容如下:

#修改数据,函数中的pk代表数据的id
def edit(request,table,pk):
    if table == ‘alionlineECS‘:
        #这是Django的一个快捷方法,通过pk去line表中取值,如果有值则返回,如果无值则抛出http404的异常
        #具体信息可参考https://docs.djangoproject.com/en/1.9/topics/http/shortcuts/
        table_ins = get_object_or_404(alionlineECS,pk=pk)
        #通过instance来将Form的数据做填充
        form = alionlineForm(request.POST or None,instance=table_ins)
        sub_title = ‘修改阿里云线上环境信息‘
    if table == ‘alifuncECS‘:
        table_ins = get_object_or_404(alifuncECS,pk=pk)
        form = alifuncForm(request.POST or None,instance=table_ins)
        sub_title = ‘修改阿里云线上环境信息‘
    if table == ‘ksonlineECS‘:
        table_ins = get_object_or_404(ksonlineECS,pk=pk)
        form = ksonlineForm(request.POST or None,instance=table_ins)
        sub_title = ‘修改金山云线上环境服务器信息‘
    if table == ‘ksfuncECS‘:
        table_ins = get_object_or_404(ksfuncECS,pk=pk)
        form = ksfuncForm(request.POST or None,instance=table_ins)
        sub_title = ‘修改金山云测试环境服务器信息‘
    if table == ‘SLB‘:
        table_ins = get_object_or_404(SLB,pk=pk)
        form = SLBForm(request.POST or None,instance=table_ins)
        sub_title = ‘修改负载均衡信息‘
    if table == ‘RDS‘:
        table_ins = get_object_or_404(RDS,pk=pk)
        form = RDSForm(request.POST or None,instance=table_ins)
        sub_title = ‘修改数据库信息‘
    #判断form是否有效
    if form.is_valid():
        #创建实例,需要做些数据处理,暂不做保存
        instance = form.save(commit=False)
        #将登录用户作为登记人,在修改时,一定要使用str强制
        if table == ‘alionlineECS‘:
            instance.ecs_signer = str(request.user)
        if table == ‘alifuncECS‘:
            instance.ecs_signer = str(request.user)
        if table == ‘ksonlineECS‘:
            instance.ecs_signer = str(request.user)
        if table == ‘ksfuncECS‘:
            instance.ecs_signer = str(request.user)
        if table == ‘SLB‘:
            instance.slb_signer = str(request.user)
        if table == ‘RDS‘:
            instance.rds_signer = str(request.user)
        #保存该实例
        instance.save()
        #跳转至列表页面,配合table参数,进行URL的反向解析
        return redirect(‘lists‘, table=table)
    context = {
        ‘table‘: table,
        ‘form‘: form,
        ‘page_title‘: ‘基础资料‘,
        ‘sub_title‘: sub_title,
    }
    #与res_add.html用同一个页面,只是edit会在res_add页面做数据填充
    return render(request,‘res_add.html‘,context)


另一个函数是delete,这个是用来删除的,内容如下:

#删除操作
def delete(request,table,pk):
    #选择相应的表格
    if table == ‘alionlineECS‘:
        #通过id值获取相应表格的实例,有值则返回,无值则抛出异常
        table_ins = get_object_or_404(alionlineECS,pk=pk)
    if table == ‘alifuncECS‘:
        table_ins = get_object_or_404(alifuncECS,pk=pk)
    if table == ‘ksonlineECS‘:
        table_ins = get_object_or_404(ksonlineECS,pk=pk)
    if table == ‘ksfuncECS‘:
        table_ins = get_object_or_404(ksfuncECS,pk=pk)
    if table == ‘SLB‘:
        table_ins = get_object_or_404(SLB,pk=pk)
    if table == ‘RDS‘:
        table_ins = get_object_or_404(RDS,pk=pk)
    #接收通过AJAX提交过来的POST
    if request.method == ‘POST‘:
        #删除该条目
        try:
            table_ins.delete()
            #删除成功,则data信息为success
            data = ‘success‘
        except IntegrityError:
            #如因外键问题,或其他问题,删除失败,则报error
            data = ‘error‘
        #将最后的data值传递至JS页面,进行后续处理,safe是将对象序列化,否则会报TypeError错误
        return JsonResponse(data,safe=False)


别忘了这里还要修改一下主urls.py,添加edit和delete:

from django.conf.urls import url,include
from django.contrib import admin
import Online.views
admin.autodiscover()
from Online import views as Online_views
urlpatterns = [
    url(r‘^admin/‘,admin.site.urls),
    url(r‘^lists/(?P<table>\w+)/$‘,Online.views.lists,name=‘lists‘),
    url(r‘^add/(?P<table>\w+)/$‘,Online.views.add,name=‘add‘),
    #基础资料的显示
    #修改数据,?P<pk>\d+代表穿过来的id值,且id值一定为数字
    url(r‘^edit/(?P<table>\w+)/(?P<id>\d+)/$‘,Online.views.edit,name=‘edit‘),
    #删除数据
    url(r‘^delete/(?P<table>\w+)/(?P<pk>\d+)/$‘,Online.views.delete,name=‘delete‘),
    url(r‘^index/‘,Online.views.index,name=‘index‘),
    url(r‘^login/‘,include(‘Online.urls‘)),
]


启动django,在浏览器里输入"外网地址:8000/lists/slb"就发现原来那个白色的界面已经运用了boostrap模板,如下:

技术分享


而打开"外网地址:8000/lists/alionlineECS",对应阿里区线上环境的资料也是套用了boostrap模板:

技术分享


当你点击“添加数据”的时候,界面也是会正确转向的:

技术分享


但是这个增加的页面很难看,白白的底儿,很挫,我们也希望这个增加的界面也有模板的样子。于是这里要用一个django-crispy-forms的app,首先在服务器里,使用#pip install --upgrade django-crispy-forms下载并安装。


然后在settings.py中加入相关app,并使其使用bootstrap3的前端。修改settings.py如下:

INSTALLED_APPS = [
    ‘django.contrib.admin‘,
    ‘django.contrib.auth‘,
    ‘django.contrib.contenttypes‘,
    ‘django.contrib.sessions‘,
    ‘django.contrib.messages‘,
    ‘django.contrib.staticfiles‘,
    ‘Online‘,
    ‘SLB‘,
    ‘RDS‘,
    #crispy app  把这个APP添加进去
    ‘crispy_forms‘,
]


然后还要在settings.py后面追加下面一句话: 

#App settings  
CRISPY_TEMPLATE_PACK = ‘bootstrap3‘


再修改add.html文件,把crispy.form应用进去:

<!--引用crispy-forms标签-->
{% load crispy_forms_tags %}
<!DOCTYPE html>
<html>
<head lang="en">  
    <meta charset="UTF-8">  
    <title></title>  
</head>
<body>
 <form method=‘POST‘ action=‘‘>{% csrf_token %}
        <!--将crispy-forms应用到form中-->
        {{ form | crispy }}
        <input type=‘submit‘ value=‘提交‘ />
 </form>
</body>
</html>


然后再返回来看看添加的界面,嗯,好像变样了:

技术分享


我们现在为了统一,把add.html改成res_add.html,同时继承index.html,将res_add.html中的内容填充到index的Container block。

{% extends "index.html" %}
<!--引用crispy-forms标签-->
{% load crispy_forms_tags %}
{% block page_title %}
    基础资料
{% endblock %}
{% block container %}
    <div class="row">
    <div class="col-sm-3 pull-left">
    <form method=‘POST‘ action=‘‘>{% csrf_token %}
        <!--将crispy-forms应用到form中-->
        {{ form | crispy}}
        <input class=‘btn btn-primary‘ type=‘submit‘ value=‘提交‘ />
        <a href="{% url ‘lists‘ table=table %}  "><input class=‘btn btn-default‘ type=‘button‘ value=‘取消‘ /></a>
    </form>
    </div>
    </div>
{% endblock %}


然后再把views.py里面add函数里面最后那一行

 return render(request,‘add.html‘,context)

 改成 

return render(request,‘res_add.html‘,context)


至此,整个添加界面就全部继承过来了:

技术分享



本文出自 “生活就是等待戈多” 博客,请务必保留此出处http://chenx1242.blog.51cto.com/10430133/1952685

以上是关于Django运维后台的搭建之五:引入databases和django-crispy-forms的主要内容,如果未能解决你的问题,请参考以下文章

Django运维后台的搭建之三:用url去精细定制与反向解析

struts2+Hibernate4+spring3+EasyUI环境搭建之五:引入jquery easyui

Django之五模型

Django框架实战:搭建一个小型的服务器运维网站

SpringBoot2.0之五 优雅整合SpringBoot2.0+MyBatis+druid+PageHelper

一天用Go快速搭建一个运维管理后台