1. 程式人生 > >Django運維後臺的搭建之五:引入databases和django-crispy-forms

Django運維後臺的搭建之五:引入databases和django-crispy-forms

連接 django databases

在上一篇,我們已經把我們做的運維外面套上了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