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