day15本節內容介紹 上節做業講解(讓行進入編輯模式,批量編輯) CSS之特殊內容補充 CSS內容補充之僞類 僞類實例:返回頂部終極版 CSS內容補充之沒法被覆蓋 jQuery插件 jQuery插件之驗證\圖片輪番和圖標 jQuery插件之jQueryUI和EasyUI jQuery插件之BootStrap介紹一.上節做業講解 思路 1.先把table畫出來 2.全選\反選\取消 3. 標識:是否進入編輯模式 id='c1' class = "edit" 未進入編輯模式 id='c1' class = "edit doing" 進入編輯模式 判斷一個標籤是否包含一個樣式用hasClass() $('#c1').hasClass('doing') 4.當前行進入編輯模式 RowIntoEdit(tr)/RowOutEdit() //tr是當前行的選擇器 一行數據,不必定每個td都是可編輯的.因此在td上要有一個屬性標示是否須要編輯. 還有,不是全部的td編輯時都使用input[type='text'],確定有的是select有的是text.因此每個td上還須要有一個屬性表示編輯的類型,是select或者text 普通內容 => input 若是是input的話,還簡單些,直接獲取td裏的text,而後放倒input裏的value <td id='xxx'>123</td> t = $(xxx).text() 建立input標籤,而且將標籤的值設置成t $(xxx).val(t) 因此對於普通的,td裏的text就是數據源 選擇 => select 對於那種選擇的,數據源去哪裏拿? select數據源去哪裏拿?首先數據源不能保存在本地,由於後端的數據常常更新. 有兩種方式: 1.經過ajax向服務端發送一個請求,服務端反回給一個數據源.這樣又多了一次請求. 2.咱們知道html是客戶端瀏覽器訪問服務端端口時反回的,因此咱們想服務端在反回的時候,能不能在js中聲明一個全局變量,當咱們須要用的時候直接使用這個全局變量就能夠獲取數據源了. 分析:第一種方式是數據源是在須要時經過ajax從服務端獲取. 第二種方式是當用戶一開始訪問請求的時候,就把數據源放倒JS裏的一個全局變量,用的時候不須要再去服務端進行請求了. 咱們使用第二種方式,咱們這裏沒有後臺,因此就在頁面直接模擬出來一個全局變量裏有些值.(若是有後臺,全局變量的存在也是必須的,至於裏面的數據是經過數據庫仍是經過ajax獲取的均可以.) 全局變量: STATU_DICT={ 1:'在線', 2:'下線', } 需求列出來了,就兩個要求: 1. td是否能夠編輯 2. 要以什麼類型方式進行編輯. 因此我要對tr行裏的元素td進行循環 判斷td裏是否有一個edit 屬性爲true,若是是true則能夠進行編輯 判斷td裏是否有一個edit-type ,它的值若是edit-type = 'input'就用普通的, 若是edit-type = 'select'就用select方式編輯,這裏要注意了,咱們要向select的數據源進行取值,固然咱們能夠在RowIntoEdit()函數中寫死,也能夠做爲參數出傳入, 寫死確定很差,做爲參數靠譜些.咱們會想,那麼咱們直接在調用函數時把變量傳入.反正是全局變量. 對沒錯,是能夠傳入變量,可是編程理念不該該這麼作,咱們要把函數想象成一個沒有思想的工具, 假如它是一個DVD一體機,有好幾張dvd唱片,你要使用dvd播放dvd時,你要動手把dvd唱片找到,而後放入到DVD,這個流程纔對. 你不能直接告訴dvd,去播放"周杰倫"的唱片.這就至關於你直接點播放按鈕,並對dvd機喊了句"周杰倫". 因此咱們要在td裏在設置一個屬性global-key = 'STATUS_DICT',標示數據源從哪一個全局變量去取. 5.退出編輯模式 <td> input</td> <td> select</td> 實例代碼:(還包含了按住ctrl鍵選擇select時批量操做!)代碼必看 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .edit-mode{ padding:10px; } .editing{ padding:10px; background-color: #ffd00f; } </style> </head> <body> <div style="padding: 20px"> <input type="button" value="全選" onclick="CheckAll('#edit_mode','#tb1');"/> <input type="button" value="反選" onclick="CheckReverse('#edit_mode','#tb1');"/> <input type="button" value="取消" onclick="CheckCancel('#edit_mode','#tb1');"/> <a id="edit_mode" class="edit-mode" href="javascript:void(0)" onclick="EditMode(this,'#tb1')" >進入編輯模式</a> </div> <table border="1"> <thead> <tr> <th>選擇</th> <th edit="true">主機</th> <th>端口</th> <th>狀態</th> </tr> </thead> <tbody id="tb1"> <tr> <td><input type="checkbox"></td> <td edit="true" edit-type="input">v1</td> <td>p1</td> <td edit="true" edit-type="select" set-val="1" global-key="STATUS_DICT">在線</td> </tr> <tr> <td><input type="checkbox"></td> <td edit="true" edit-type="input">v2</td> <td>p2</td> <td edit="true" edit-type="select" set-val="1" global-key="STATUS_DICT">在線</td> </tr> <tr> <td><input type="checkbox"></td> <td edit="true" edit-type="input">v3</td> <td>p3</td> <td edit="true" edit-type="select" set-val="1" global-key="STATUS_DICT">在線</td> </tr> </tbody> </table> <script src="jquery-3.1.0.min.js"></script> <script > STATUS_DICT = [ {'id': 1, 'value': "在線"}, {'id': 2, 'value': "下線"} ]; $(function(){ BindSingleCheck('#edit_mode','#tb1'); }); function BindSingleCheck(mode,tb){ $(tb).find(':checkbox').bind('click',function(){ var tr = $(this).parent().parent(); if($(mode).hasClass('editing')){ if($(this).prop('checked')){ RowIntoEdit(tr) }else{ RowOutEdit(tr) } } }); } /* 監聽是否已經按下control鍵 */ window.globalCtrlKeyPress = false; window.onkeydown = function (event) { console.log(event.keyCode); if(event && event.keyCode == 17){ window.globalCtrlKeyPress = true; console.log('ctrl + ok') } }; window.onkeyup = function (event) { if(event && event.keyCode == 17 ){ window.globalCtrlKeyPress = false; console.log('ctrl -----ok') } }; // 寫一個建立select標籤的函數 function CreateSelect(attrs,csses,option_dict,item_key,item_value,current_val){ var doc = document; var sel = doc.createElement('select'); $.each(attrs,function(k,v){ $(sel).attr(k,v); }); $.each(csses,function(k,v){ $(sel).attr(k,v) }); $.each(option_dict,function(k,v){ var opt1 = doc.createElement('option'); var sel_text = v[item_value]; var sel_value = v[item_key]; if(sel_value == current_val) { $(opt1).text(sel_text).attr('value', sel_value).attr('text', sel_text).attr('selected',true).appendTo($(sel)); }else{ $(opt1).text(sel_text).attr('value', sel_value).attr('text', sel_text).appendTo($(sel)); } }); return sel; } // 寫一個當select變化時,批量修改下面的值和當前值一致 function MultiSelect(ths){ console.log('33333'); if(window.globalCtrlKeyPress){ console.log('171717171'); var index = $(ths).parent().index(); var value = $(ths).val(); $(ths).parent().parent().nextAll().find(':checkbox').each(function(){ $(this).parent().parent().children().eq(index).children().val(value) }) } } //寫一個將行變成編輯模式的函數 function RowIntoEdit(tr){ // console.log('1111') tr.children().each(function(){ //$(this), 當前循環元素,當前td if($(this).attr('edit') == 'true'){ if($(this).attr('edit-type') == 'select' ){ //在線,對應的value值 var select_val = $(this).attr('set-val'); // global_key全局變量的變量名 var global_key = $(this).attr('global-key'); //建立一個select標籤,而且讓select標籤默認選中當前的值 /* <select onchange="MultiSelect(this);"> <option value="1" selected="selected">在線</option> <option value="2">下線</option> </select> */ var select_tag = CreateSelect({"onchange":"MultiSelect(this)"},{},window[global_key],'id','value',select_val); /*這裏有一個特殊的window[global_key],這個是幹什麼的呢? 舉個例子,如今有一個全局變量 A = [11,22] 直接調用console.log(A)打印記過 [11,22] 使用console.log(window['A']) 打印結果也是[11,22],因此 window['A'] 就是變量A的用字符的表達方式, 這裏global_key = 'global-key',因此 window['global-key'] 就至關於直接調用變量global-key */ //把建立後的select標籤,換到當前td中 $(this).html(select_tag) }else{ var orgin_value = $(this).text(); var temp = "<input value='" +orgin_value +"'>"; $(this).html(temp); } } }) } //寫一個行退出編輯模式的函數 function RowOutEdit(tr){ tr.children().each(function(){ if($(this).attr('edit') == 'true'){ if($(this).attr('edit-type') == 'select'){ var new_val = $(this).children(':first').val(); var new_text = $(this).children(':first').find("option[value = '" +new_val+"']").text(); $(this).attr('set-val',new_val); $(this).text(new_text); }else{ var orgin_value = $(this).children().first().val(); $(this).text(orgin_value); } } }); } //全選按鈕調用的函數,函數檢查是否在編輯模式下進行的全選,若是是則將全部的行選中而且循環每行調用RowIntoEdit(tr),若是不是則直接全選中 function CheckAll(mode,tb){ // mode = '#edit-mode' // tb = '#tb' //判斷是否在編輯模式,若是是 if($(mode).hasClass('editing')){ //選中全部的checkbox,並將全部行進行處理成進入編輯模式. $(tb).children().each(function(){ //找到tr var tr = $(this); //找到tr下的checkbox var check_box=tr.children().first().find(':checkbox'); if(check_box.prop('checked')){ }else{ //選中 check_box.prop('checked',true); RowIntoEdit(tr); } }) //若是不在編輯模式下,直接全選 } else { $(tb).find(':checkbox').prop('checked',true); } } //反選按鈕調用的函數,函數檢查是否在編輯模式下進行的全選,若是是反選的同時調用RowIntoEdit和RowOutEdit,若是不是直接反選 function CheckReverse(mode,tb){ //判斷是否進入編輯模式 if($(mode).hasClass('editing')){ $(tb).children().each(function(){ var tr = $(this); var check_box = tr.children().first().find(':checkbox'); if(check_box.prop('checked')){ check_box.prop('checked',false); RowOutEdit(tr) }else{ check_box.prop('checked',true); RowIntoEdit(tr) } }); //若是不在編輯模式,則直接反選 }else{ $(tb).find(':checkbox').each(function(){ var check_box = $(this); if(check_box.prop('checked')){ check_box.prop('checked',false); }else{ check_box.prop('checked',true); } }) } } //取消按鈕調用的函數,首先判斷是否在編輯模式下,若是是則取消並調用RowOutEdit函數,若是不是則直接取消 function CheckCancel(mode,tb){ if($(mode).hasClass('editing')){ $(tb).children().each(function(){ var tr = $(this); var check_box = tr.children().first().find(':checkbox'); if (check_box.prop('checked')){ check_box.prop('checked',false); //當前行退出編輯模式 RowOutEdit(tr); } }); }else{ $(tb).find(':checkbox').prop('checked',false); } } //點擊"進入編輯模式"時調用的函數. function EditMode(ths,tb){ var mode = $(ths); //若是點擊前是編輯模式,點擊後爲非編輯模式,咱們就要找到正在編輯的行tr,並使用RowOutEdit(tr) if(mode.hasClass('editing')){ mode.removeClass('editing'); $(tb).children().each(function(){ var tr = $(this); var check_box = tr.children().first().find(':checkbox'); if(check_box.prop('checked')){ RowOutEdit(tr) } }); //若是以前不是編輯模式,則進入,並循環循環行,檢測是否checked,選中的進入編輯模式 } else{ mode.addClass('editing'); $(tb).children().each(function(){ var tr = $(this); var check_box = tr.children().first().find(':checkbox'); if(check_box.prop('checked')){ RowIntoEdit(tr); } }) } } </script> </body> </html>二.jQuery插件介紹 jQuery插件之驗證\圖片輪番和圖標 jQuery插件之jQueryUI和EasyUI jQuery插件之BootStrap介紹 -- parsleyjs http://parsleyjs.org/ -- jQuery Validate http://jqueryvalidation.org/ -- bxslider http://bxslider.com/ -- Bootstrap http://www.bootcss.com/ -- Font Awesome http://fontawesome.io/ -- jQuery EasyUI http://www.jeasyui.com/download/index.php -- jQuery UI http://jqueryui.com/ BootStrap介紹 如今不少網站都在搞BootStrap,它即適用後臺,也適用於前臺. 1.bootStrap中提供了各類好看的格式工具.不是用了bootstrap就能作出美觀的網站,仍是要看你本身的本事. 2.BootStrap是響應式的 什麼是響應式,有些網站當窗體大時,選項列出來,若是窗體小時選項就放倒一個圖標,點擊時才顯示. 這個功能咱們可使用js寫一個事件,用if else也能實現.可是若是應用css中一個樣式也能夠實現: @media (min-width:768px){ .lead{ font-size:21px; } } 這裏@media關鍵字後面定義了min-width:768px(最小寬度),意思只有當窗體寬度大於768px時裏面的lead樣式才生效. @media後面能夠跟mediatype選項,意思是對於哪些項目才生效響應式的配置如 @media (min-width:768px) 括號裏面設置條件,這裏指窗體寬度最小值爲768. @media all 用於全部設備,至關於上面的括號的條件 @media aural 已廢棄.用於語音和聲音合成器.至關於上面的括號的條件 @media braille 已廢棄. 用於盲文觸摸式反饋設備. 至關於上面的括號裏的條件 @media embossed 已廢棄. 用於打印的盲人印象設備.至關於上面的括號裏的條件 @media handheld 已廢棄. 用於掌上設備或者更小的設備.至關於上面的括號裏的條件 @media print 用於打印機和打印預覽.至關於上面的括號裏的條件 @media projection 已廢棄.用於投影設備.至關於上面的括號裏的條件 @media screen 用於電腦屏幕,平板電腦,智能手機等.至關於上面的括號裏的條件. 最經常使用的就是用屏幕大小進行判斷. @media speech 應用於屏幕閱讀器等發聲設備.至關於上面的括號裏的條件 @media tty 已廢棄. 用於固定的字符網格,如電視\終端設備和字符有限制的便攜設備.至關於上面的括號裏的條件 @media tv 已廢棄. 用於電視和網絡電視.至關於上面的括號裏的條件 邏輯判斷 and,且 not,非 only,只有 媒體功能 aspect-ratio 定義輸出設備中的頁面可見區域寬度與高度的比率 color 定義輸出設備每一組彩色原件的個數.若是不是彩色設備,則值等於0 color-index 定義在輸出設備的彩色查詢表中的條目數.若是沒有使用彩色查詢表,則值等於0 device-aspect-ratio 定義輸出設備的屏幕可見寬度與高度的比率. device-height 定義輸出設備的屏幕可見高度. device-width 定義輸出設備的屏幕可見寬度. grid 用來查詢輸出設備是否使用柵格或點陣. height 定義輸出設備中的頁面能夠區域高度. max-aspect-ratio 定義輸出設備的屏幕可見寬度與高度的最大比率. max-color 定義輸出設備每一組彩色原件的最大個數. max-color-index 定義在輸出設備的彩色產訊表中的最大條目數. max-device-aspect-ratio 定義輸出設備的屏幕可見寬度與高度的最大比率. max-device-height 定義輸出設備的屏幕可見的最大高度. max-device-width 定義輸出設備的屏幕最大可見寬度. max-height 定義輸出設備中的頁面最大可見區域高度. max-monochrome 定義在一個單色框架緩衝區中每像素包含的最大單色原件個數 max-resolution 定義設備的最大分辨率. max-width 定義輸出設備中的頁面最大可見區域寬度. min-aspect-ratio 定義輸出設備中的頁面可見區域寬度與高度的最小比率. min-color 定義輸出設備每一組彩色原件的最小個數. min-color-index 定義在輸出設備的彩色查詢表中餓最小條目數. min-device-aspect-ratio 定義輸出設備的屏幕可見寬度與高度的最小比率. min-device-width 定義輸出設備的屏幕最小可見寬度. min-device-heigth 定義輸出設備的屏幕的最小可見高度. min-height 定義輸出設備中的頁面最小可見區域高度. min-monochrome 定義在一個單色框架緩衝區中每像素包含的最小單色原件個數 min-resolution 定義設備的最小分辨率 min-width 定義輸出設備中的頁面最小可見區域寬度. monochrome 定義在一個單色框架緩衝區中每像素包含的單色原件個數.若是不是單色設備,則值爲0 orientation 定義輸出設備中的頁面可見區域高度是否大於或等於寬度. resolution 定義設備的分辨率. 如:96dpi,300dpi,118dpcm scan 定義電視類設備的掃描工序 width 定義輸出設備中的頁面可見區域寬度. 能設置最小寬度,能不能設置最大寬度?能,代碼以下: @media screen and (max-width:1000px) and (min-width: 800px){ body{ background-color:red; } } @media screen and (max-width: 800px){ body{ background-color: green; } } 上面是頁面響應式的原理.咱們說bootstrap是響應式的,是說bootstrap利用這些原理,經過調用bootstrap提供的方法能夠實現響應式樣式. 具體怎麼用,課堂上沒說,能夠瀏覽bootstrap網頁關於響應式設置的內容.你要知道的是bootstrap支持響應式的網頁三.CSS特殊內容補充 CSS內容補充之僞類(又稱僞元素) 什麼是僞類用語言很差描述,只能描述僞類的功能. 假若有一個css樣式以下: .add{} 那麼當一個div標籤若是定義了class='add',div標籤就會應用.add裏定義的樣式.這是普通狀況下的執行過程. 接下來咱們使用CSS的僞類,將.add{}代碼更改爲以下: <style> .add:after{ background-color: #ffd00f; content:'sb'; } </style> <body> <div class='add'>alex</div> </body> 上面咱們看到.add:after ,after就是僞類,也稱爲僞元素. 咱們在頁面上看到的結果就是: alexsb 可是要注意的時 只有 sb 兩個字符是有background-color設置的背景色.而alex這四個字符是沒有背景色的.而且在頁面中是沒法選中.(因此當你一個標籤應用了含有僞類的css樣式,那麼這個標籤自己不會應用樣式裏設置的屬性,只是僞元素自己應用樣式裏設置的屬性.) 默認狀況是這樣了,BootStrap在僞元素裏作了一個加工,把'sb'換成字體文件裏的unicode編碼,好比'u2709',這樣,在alex後面出現的就不是sb了,而是一個圖標. 好比在BootStrap中的css文件源碼中有這麼一段樣式代碼: .glyphicon-envelope:before{ content:"\2709" /* \2709就是字體文件的unicode編碼,當執行這段代碼時就會瀏覽器就會去字體文件中取unicode編碼爲2709的圖標*/ } 當標籤調用這個樣式時,就會在標籤text的前面加上圖標,這個就是BootStrap插件實現調用css樣式實如今調用標籤的前面或後面顯示圖標的原理. 學了僞類和BootStrap總結亮點: 1.xxx:after,before (聯合content使用)這種定義的css是僞類,內容先後插入數據 2.bootstrap 是經過僞類 和 字體對應關係 來實現的 那麼問題來了,利用僞類能作什麼?有一個經常使用的,以前咱們在學css樣式的float時,知道在使用float的時候,要在最後加一個clear=both,以下: <style> .c2{ background-color: #ffd00f; } </style> <body> <div class="c2"> <div style="float: left;">11</div> <div style="float: left;">22</div> <div style="clear: both;"></div> </div> </body> 緣由是一個標籤裏沒有內容是不顯示的.因此想顯示背景色,就要把float的拉下來. 那咱們如今學了僞類就可使用僞類來實現了:(把c2改爲僞類c2:after,當div應用了c2樣式,讓after自動加一個內容,而且clear=both) 代碼以下: <head> <meta charset="UTF-8"> <title>Title</title> <style> .c2{ } .c2:after{ content:'.'; /*在應用c2樣式的標籤後加一個'.',由於div標籤或者其餘標籤只有當有值的時候纔會撐起來*/ clear: both; /*定義僞元素的clear爲both*/ visibility: hidden; /*讓這個僞類隱藏*/ } </style> </head> <body> <div class="c2"> <div style="float: left;">11</div> <div style="float: left;">22</div> </div> </body> 上面的代碼實現了使用僞類把div撐起來的做用,咱們想一個html中可能有不少使用了float的div標籤.因此能不能定義一個你們都能使用的僞類. 因此上面的代碼就能夠改爲: <head> <meta charset="UTF-8"> <title>Title</title> <style> .c2{ } .clearfix:after{ content:'.'; /*在應用c2樣式的標籤後加一個'.',由於div標籤或者其餘標籤只有當有值的時候纔會撐起來*/ clear: both; /*定義僞元素的clear爲both*/ visibility: hidden; /*讓這個僞類隱藏*/ } </style> </head> <body> <div class="c2 clearfix"> //這裏應用了兩個class, <div style="float: left;">11</div> <div style="float: left;">22</div> </div> </body> 這樣寫實現了兩個好處: 1.不用每次在div裏多加一條<div clear='both'><div> 標籤了,讓css樣式自動加了 2.不用爲每個div加一個僞類了.只須要在div應用一個指定的clear樣式便可. 爲類實例:返回頂部終極版(返回頂部已經到極致了,沒有比這在牛逼的了) 有些網頁右下方有返回頂部,當你鼠標沒有移動上去的時候,是一個圖標,鼠標移上後就是"返回頂部"字符串.這個如何實現 咱們能夠經過js,綁定事件,這樣固然能夠實現,可是這樣實現就是每個有返回頂部功能的頁面都要引用這個js. 這時候就可使用僞類來實現,定義當鼠標放上去的時候,就調用after,加上樣式和僞類.具體代碼以下: .gotop:hover:after{ top:0; left:0; width:100%; height:100%; content: ""; position: absolute; } 咱們知道.gotop:hover{} 的意思是當鼠標移動到上面應用該樣式.而.gotop:hover:after{}的意識是當鼠標移動到上面,在class="gotop"標籤內容後面應用該樣式 CSS內容補充之沒法被覆蓋四.講述上面知識點(二)的目的是介紹bootstrap的實現響應式的原理,講解知識點(三)的目的是介紹bootstrap引用圖標的實現原理.這兩點都是針對css的.bootstrap也有js部分.js 的部分咱們在使用的時候講解,ps:bootstrap的全部的js都是基於jQuery實現的.因此在導入bootstrap的js前要先導入jQuery.接下來說解bootstrap的使用 1. 下載導入 2. css head 3. js body底部 a.先倒入jQuery,版本要是2.1.4以上 b.再導入bootstrap 那到底bootstrap能對整個html作哪些定義呢? 4. 能夠定義頭部信息 <meta charset="utf-8"> 編碼 <meta http-equiv="X-UA-Compatible" content="IE=edge"> Bootstrap 不支持 IE 古老的兼容模式。爲了讓 IE 瀏覽器運行最高級別的可用模式渲染顯示內容 <meta name="viewport" content="width=device-width, initial-scale=1"> 爲了確保適當的繪製和觸屏縮放,須要在 <head> 之中添加 viewport 元數據標籤。 在移動設備瀏覽器上,經過爲視口(viewport)設置 meta 屬性爲 user-scalable=no 能夠禁用其縮放(zooming)功能。這樣禁用縮放功能後,用戶只能滾動屏幕,就能讓你的網站看上去更像原生應用的感受。注意,這種方式咱們並不推薦全部網站使用,仍是要看你本身的狀況而定! (最直觀的是在手機上是否是容許用兩個手指進行放大縮小) <meta name="renderer" content="webkit"> 國內瀏覽器廠商通常都支持兼容模式(即 IE 內核)和高速模式(即 webkit 內核),不幸的是,全部國產瀏覽器都是默認使用兼容模式,這就形成因爲低版本 IE (IE8 及如下)內核讓基於 Bootstrap 構建的網站展示效果很糟糕的狀況。幸運的是,國內瀏覽器廠商逐漸意識到了這一點,某些廠商已經開始有所做爲了 目前只有360瀏覽器支持此 <meta> 標籤。但願更多國內瀏覽器儘快採起行動、儘快進入高速時代! (其實就是說好多瀏覽器的內核是IE瀏覽器內核,可是IE瀏覽器內核低版本又不支持響應式佈局,bootstrap有由於這個來出解決方案,即便解決了效率也變底了.而使用<meta>屬性就能夠設置瀏覽器使用chrom瀏覽器內核.可是又不是全部的瀏覽器有這個屬性.) (對於如今的開放,你就不用考慮IE瀏覽器了,由於IE6\7早該被淘汰了) ps:其實對於bootstrap這個插件來講,你要想把它的全部功能都應用上,其實很費勁的,爲何呢?就是由於IE瀏覽器的存在.IE很爛. bootstrap2文件結構以下,其中bootstrap-responsive.css和bootstrap-responsive.min.css這兩個文件的存在的意義很大程度上就是爲了解決IE瀏覽器響應式佈局的,有的IE版本6\7是不支持響應式佈局的.解決掉了,可是效率也變得底了. bootstrap2 ├── css │ ├── bootstrap-responsive.css │ ├── bootstrap-responsive.min.css │ ├── bootstrap.css │ └── bootstrap.min.css ├── img │ ├── glyphicons-halflings-white.png │ └── glyphicons-halflings.png └── js ├── bootstrap.js └── bootstrap.min.js body中請查看bootstrap官網文檔. PS:之後在寫頁面的時候,在最外層加一個最小寬度,這樣當縮小網頁時,兩個float的div纔不會堆疊,而是出現左右的滾動條.五.更改框架 假如咱們如今使用了框架,寫了一個html.框架的背景色是紅色,我如今想把背景色改爲灰色,該如何修改. 理論上咱們直接寫一個css樣式,而後在body處用上class等於咱們自定義的css樣式文件便可.可是實際上即便你使用了,也不起任何做用.爲何? 緣由是框架裏設置的css樣式都用到了優先級,聲明瞭框架裏的樣式優先級高.如: <style> .c1{ background-color: #2aabd2 !important; } .c2{ background-color: #2b669a; } </style> 在屬性後面加了!important,標示我最牛逼,大家誰也代替不了我. 那麼咱們應該如何作,才能改呢.固然是在c2裏定義的屬性也加上!important,這樣兩個都是最牛逼的在一個級別上,又遵循從上到下的順序了. !important這個就是知識點三中提到的css樣式補充之沒法覆蓋的內容.六.Web框架七.DjangoDjango 框架基礎 1.安裝 pip install django=1.9.5 2.建立Django程序 咱們想,咱們建立本身的Django程序以前,是否是要拿到Django框架的基礎文件.因此咱們在腦中想象,有兩步驟1.拿到django框架的基礎文件.2.建立本身的APP程序 知道建立Django程序有兩步後,咱們又要知道建立的方式有兩種(). a.命令方式 django-admin startproject project名字 例子: django-admin startproject mysite 當執行此命令時,咱們就建立了一個名爲mysite 的django工程 cd mysite 進入咱們建立的工程目錄,這時候查看下目錄結構以下 ls -l -rwxr-xr-x 1 tedzhou staff 249 8 1 13:17 manage.py 用於在此工程目錄下建立程序項目的腳本程序,好比咱們在此工程目錄中建立cmdb程序項目,建立monitor程序項目,建立openstacks程序項目等 drwxr-xr-x 6 tedzhou staff 204 8 1 13:17 mysite 此目錄下有一個同名工程目錄的目錄,此目錄下放了一些配置文件. python manage.py startapp app01 建立app01 python manage.py startapp app02 建立app02 再次查看目錄結構以下: $ ls -l drwxr-xr-x 9 tedzhou staff 306 8 1 13:21 app01 建立出來的程序項目app01 drwxr-xr-x 9 tedzhou staff 306 8 1 13:21 app02 建立出來的程序項目app02 -rwxr-xr-x 1 tedzhou staff 249 8 1 13:17 manage.py drwxr-xr-x 7 tedzhou staff 238 8 1 13:21 mysite b.使用phcharm工具進行建立工程項目project,建立app時仍是須要在終端進行建立 建立Django程序 終端,python manage.py startapp app0 -windows 若是在mac中,在建立過Django程序的前提下按 option+R組合鍵,彈出一個配置界面. 使用django框架配置本身的程序. 咱們建立好Django工程而且建立了本身的app後.有如下幾個文件須要關注 mysite/manage.py 這個是至關於本身框架中的main程序.同時又是建立app的腳本文件和執行django程序的腳本文件 mysite/mysite/urls.py 至關於本身框架文件中的urls.py文件,用於訪問路由至關於映射,你訪問/admin/路徑映射到一個函數,訪問/home/映射到一個函數 mysite/mysite/settings 全局配置文件,可配置BASE_DIR目錄,templates目錄的地址,等等其餘的...具體用的時候天然會知道 mysite/app01/models.py 至關於本身框架中的models.py,配置鏈接後臺數據庫的方法.這個只能是文件,不能搞成目錄,由於Django框架就是這麼定的 mysite/app01/views.py 至關於本身框架中的views目錄,這裏是文件,咱們能夠建立一個目錄叫作views目錄,而後再在目錄中在根據不一樣的業務把函數按文件分爲:帳戶登錄相關views/account.py ,用戶信息相關views/userInfo.py等等 mysite/templates/ 這是一個目錄,目錄中放了一些html的模版文件,文件裏使用jinja2的語法. 模擬一個用戶請求Django框架的流程 用戶請求 -> mysite/mysite/urls.py(判斷請求的地址作路由) -> mysite/app01/views.py(取相應的函數) -> models.py(拿到數據庫數據) --> 將結果返回給請求者 (over) -> templates/* (取html模版文件) 3.執行django程序 進入project項目 python manage.py runserver 127.0.0.1:8000 點pycharm > 4.Django依賴數據庫 配置:settings 生成數據庫表: python manage.py makemirations # 生成配置文件 python manage.py migrate # 根據配置文件建立數據庫相關 5.admin Django是一個特別全,特別牛逼的框架.爲何說它牛逼,它比其餘框架提供的功能要多.好比ORM關係對象映射,咱們學過sqlachemy,而Django本身就有一套ROM.另外Django還有一個網站後臺.而admin就是用來配置後臺的. 咱們在瀏覽器輸入http://127.0.0.1:8000/admin咱們會看到後臺的登錄界面,這裏默認是沒有用戶名和密碼的.後面會說admin用戶名和密碼是如何建立的. admin就是配置後臺的,好比說咱們以前鏈接數據庫,以及進行基本的增刪改查,是須要經過數據庫終端進行操做.Django中的admin就是讓你快速的數據庫的.好比咱們經過Django的ORM來操做數據庫.首先建立類,而後經過類操做表(建立表,對數據進行增刪改查).一個類就是一個表. 這時候咱們就能夠把咱們建立的Django的ORM類註冊到admin,就能夠經過admin後臺對註冊的類進行快速的增刪該查.老男孩教育Alex作的那個點名的表就是使用admin進行配置後把功能實現的.具體怎麼配置咱們後面會學到,如今先知道Django有admin這個後臺管理便可. 而且Django的厲害之處還有單元測試.這個如今還涉及不到. 另外咱們看下app01程序目錄下有這麼一個文件夾:migrations,這個文件夾是作什麼用的呢? 咱們以前學習sqlachemy的時候,知道sqlachemy不能對錶結構進行修改.而Django中的ORM類就能夠實現對錶結構的修改.它是怎麼實現的呢?它的實現就和migrations文件夾有關係了. sqlachemy中建立表,只須要一個命令就在數據庫裏就生成一個表,而Django框架中的ORM類就不是直接經過命令建立了,它須要兩步:第一步,使用一個命令生成一個配置文件,第二步再使用一個命令根據配置文件作數據庫的操做. 至關於若是在Django中作數據庫變動,或者要刪除表中的一個字段或者增長一個字段再或者改變一個字段的類型.你都須要先使用一個命令生成中間的配置文件(至關於代碼),在根據配置文件操做數據庫,這個配置文件放在哪呢?就是放在migrations文件夾內. 上面的內容都是admin的基本的介紹. 咱們在說一個知識點,對於Django的admin是須要用戶名和密碼的.那這個用戶名密碼前面咱們說默認是沒有的.那咱們要進行建立.建立在哪裏保存呢?哈哈,Django之可以提供admin後臺那麼強大的功能的前提是,它是須要一些數據源進行支撐的. 因此當咱們使用django-admin startproject mysite建立一個Django工程的時候會默認建立一個db.sqlte3 庫,可是默認庫裏是沒有表的,須要執行初始化命令進行建立的. 咱們能夠在mysite/mysite/settings.py文件裏找到關於初始化數據庫的位置如: # Database # https://docs.djangoproject.com/en/1.9/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } 在settings.py文件中咱們找到了初始化db文件的路徑爲os.path.join(BASE_DIR, 'db.sqlite3') 咱們知道初始化時候會有一個sqlite數據庫.那麼咱們就能夠在這個庫裏建立admin後臺的管理帳戶了.那麼怎樣建立呢?前面說了在Django中建立一個表須要兩個步驟.1.生成配置文件.2.根據配置文件操做數據庫.固然操做初始庫也不能例外. 生成數據庫表: python3.5 manage.py makemigrations # 生成配置文件 python manage.py migrate # 根據配置文件建立數據庫相關 執行完初始化數據庫命令後,就可使用命令建立後臺管理帳戶了,同時咱們可使用navicat for sqlite查看都建立了哪些表. python manage.py createsuperuser ... 用戶 ted 密碼 Zh.... http://localhost:8000/admin 至此,咱們關於Django框架自帶的後臺管理功能admin暫時瞭解到這,後面會有專門章節進行講解. 6.路由系統 咱們學Django就是爲了用它.用它來作咱們的項目. 對於Django請求到來以後現到達路由系統,那麼對於路由系統的配置,須要配置什麼. 咱們知道在django框架中,project_name/project_name/urls.py文件是路由系統的文件,也就是說全部路由系統的配置都和這個文件有關.爲何說有關,而不是就配置這個呢? 由於存在二級路由的方式. 初始化時urls.py文件內容: from django.conf.urls import url from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), ] 1.靜態路由 就是簡單的url(r'^home/', admin.site.urls),寫死的URL from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', views.home), ] 同時在app01中定義home: from django.shortcuts import render from django.shortcuts import HttpResponse # Create your views here. # 在Django裏面全部處理請求的函數必須有一個request參數,緣由是全部的函數都是Django框架內部調用的,調用的時候把用戶請求的數據封裝到request中,Django框架在根據路由選擇,調用views裏函數時再把請求的信息封裝成request穿入函數. # def home(request): # 咱們本身寫的框架能夠直接返回字符串.而在Django中,函數中return時不能直接返回字符串,須要用框架中的HttpResponse模塊封裝. # request 'aaaaa' return HttpResponse('222222 OK') 2.動態路由 咱們常常看到,若是頁面上的內容不少時,會有分頁.當咱們訪問分頁時,每每只是URL後面的數字不同如: http://www.cnblogs.com/#p2 第二頁 http://www.cnblogs.com/#p3 第三頁 http://www.cnblogs.com/#p4 第四頁 那咱們確定不能在路由中寫上這每一頁的URL,這尼瑪不科學.那麼怎麼寫呢? urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', views.home), url(r'^news/(\d+)', views.news), #這裏咱們設置news/(\d+),\d+爲正則表達式, ] 而後在app01下的views在定義一個news def news(request,nid): #request,必須有,沒得選擇就像類裏的self同樣,必須有 return HttpResponse(nid) 這樣咱們就能夠訪問: http://127.0.0.1:8000/news/66 http://127.0.0.1:8000/news/11 http://127.0.0.1:8000/news/22 咱們想既然能夠匹配一個參數,能不能匹配兩個呢?固然能夠,以下 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', views.home), url(r'^news/(\d+)', views.news), url(r'^shop/(\d+)/(\d+)', views.shop), ] 這時咱們在app01/views.py要定義一個shop函數 def shop(request,nid1,nid2): #這裏咱們傳入了兩個參數. nid = nid1+nid2 return HttpResponse(nid) 這裏切記,參數嚴格按照順序進行賦值. 那麼有沒有辦法,讓路由裏的參數和views裏的函數對應上呢,這樣傳入函數時,就不須要留意順序了,有,以下: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', views.home), url(r'^news/(\d+)', views.news), url(r'^shop/(\d+)/(\d+)', views.shop), url(r'^page/(?P<n1>\d+)/(?P<n2>\d+)', views.page), # 這裏(?P<n1>/d+)就指定了我第一個匹配的數字傳給n1形式參數,第二個匹配的值傳給n2這個形式參數. ] 這時,咱們在app01/views.py裏定義個page函數 def page(request,n2,n1): #此時n1,n2的位置就沒必要在乎了,可是變量名必定要和urls配置的同樣 nid = n1+n2 return HttpResponse(nid) 總結: 按照順序,按n個匹配的數據,交給函數的第N個參數,嚴格按照順序 模版的方法,將匹配的參數,傳給指定的形式參數 3.二級路由 咱們假設mysite 是Django工程,在裏面有兩個app項目app01和app02,兩個項目又都有home目錄和page目錄, 咱們此時要是在mysite/mysite/urls.py裏進行路由,那尼瑪就麻煩了.由於app01和app02都要經過views裏的函數進行處理,兩個名字同樣了,固然你能夠經過別名,可是那樣low,我們有高大上的作法. 咱們假設每個程序目錄本身有一個urls.py文件,讓訪問app01目錄下的全部請求去app01/urls.py去路由,訪問app02目錄下的請求,去找app02/urls.py去路由.就完美了.怎樣實現呢? 以下: 在mysite/mysite/urls.py文件配置以下 from django.conf.urls import url,include # 導入include,用於加載app01和app02目錄下的urls文件 from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', views.home), url(r'^news/(\d+)', views.news), url(r'^shop/(\d+)/(\d+)', views.shop), url(r'^page/(?P<n1>\d+)/(?P<n2>\d+)', views.page), url(r'^app01/', include('app01.urls')), #設置當訪問app01/下的請求時,使用app01.urls進行路由 url(r'^app02/', include('app02.urls')), #設置當訪問app02/下的請求時,使用app02.urls進行路由 ] 在mysite/app01/urls.py 這個文件默認不存在,能夠從mysite目錄下拷貝,配置以下: from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^home/', views.home), ] 在mysite/app01/views.py定義home函數 def home(request): # 咱們本身寫的框架能夠直接返回字符串.而在Django中,函數中return時不能直接返回字符串,須要用框架中的HttpResponse模塊封裝. # request 'aaaaa' return HttpResponse('APP01.home') 在mysite/app02/urls.py 這個文件默認不存在,能夠從mysite目錄下拷貝,配置以下: from django.conf.urls import url from django.contrib import admin from app02 import views urlpatterns = [ url(r'^home/', views.home), ] 在mysite/app02/views.py定義home函數 from django.shortcuts import render from django.shortcuts import HttpResponse # Create your views here. def home(request): return HttpResponse("app02.home") #這裏必定要用HttpResponse進行封裝,我都忘記不少次了. 這時咱們在瀏覽器訪問我測試: 訪問http://127.0.0.1:8000/app02/home/ 顯示app02.home http://127.0.0.1:8000/app01/home/ 顯示APP01.home 總結: app01 url.py project_name url: app01 -> include("app01.url") 7.基本的數據庫操做 咱們學過sqlalchemy,是ORM框架關係對象 ORM框架 code first 代碼優先 本身寫類 -> 而後根據類建立數據庫表 db first 本身命令建立數據庫表和字段 -->根據表建立類 (不懂) 上面兩個最終仍是使用類進行數據操做.code first更省事,而對於db first先修改數據庫,在根據庫生成類.具體咋整的先不用明白. Django框架內部有本身的orm框架,它的ORM框架類型也是code first ,即先寫類在建立數據庫表 具體的實例: 咱們前面在mysite工程項目裏建立了兩個APP:app01和app02 這兩個app項目裏都有models.py文件. 這裏咱們就能夠利用app01/models.py文件生成app01程序項目裏須要的表. 利用app02/models.py文件生成app02程序項目裏須要的表.這樣公用一個數據庫分別生成本身程序須要的表,這樣的華兩個程序之間沒有表的關聯下降了兩個程序之間的耦合,若是它們之間須要通信,就須要經過API進行交互.之後會學如今先知道下須要經過API 咱們知道建立表,先建立類,類生成表.類就須要放到models裏面.對於models裏面要想建立一個類,就須要使用Django框架裏的ORM的模塊以及語法. 因此咱們要掌握的是如何使用Django框架裏的ORM框架進行建立類.以及實例化類後的對象的增刪改查的語法. 1.在Django框架中建立ORM類,而後建立一個表的步驟. 在app01/models.py文件中建立ORM類 from django.db import models class UserInfo(models.Model): # 建立一個UserInfo類,一個類就是一個表 username = models.CharField(max_length=32) # username字段,類型爲CharField,類型爲CharField的時候,後面必須跟(max_length=32) password = models.CharField(max_length=32) # password字段 age = models.IntegerField() # age字段 # 至此咱們就建立了一個類,接下來就能夠命令先建立配置文件,而後在執行配置文件了. python manage.py makemirations # 生成配置文件 python manage.py migrate # 根據配置文件建立數據庫相關 可是 咱們執行上面兩個命令如今還不能成功,爲何呢?你想啊,以前咱們初始化Django數據庫時能成功,那是配置文件裏有admin的信息.咱們如今要給本身建立的app項目建立表,而且使用的models文件路徑在app01/models.py 試問,執行python manage.py makemirations 這個命令時,它如何才能找到app01/models.py文件呢?因此固然要在全局配置文件mysite/mysite/settings.py進行以下配置: 1.首先把本身的項目名稱,在INSTALLED_APPS序列裏 # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', #在最後加上你本身的app項目的名字.切記後面要有逗號.這樣Django程序就會主動找app01/models.py文件 ] 在settings.py文件裏進行設置完成後,在執行那兩個命令. python manage.py makemirations # 生成配置文件,此時在app01/migrations/目錄下多出一個配置文件0001——initial.py python manage.py migrate # 根據配置文件建立數據庫相關,其實就是執行上面那個配置文件 執行完成後,咱們使用navicat for sqlite工具查看錶,會多出一個表,表名爲: app01_userinfo 這裏Django默認把項目app01的表加了前綴爲app01_userinfo .是否是超級智能. OK,到此咱們就掌握瞭如何爲APP項目配置本身的models.py文件,並在models.py文件裏建立類的方法. PS: 咱們建立數據表時只給了username,password,age三個字段,在執行python manage.py makemirations命令後,配置文件中自動添加一個id字段爲自增且主鍵的屬性.高級把,可是咱們若是在類中設置了主鍵,就不會自動添加了.可查看0001——initial.py文件. 2.接下來,要學會如何利用已經在models.py文件裏建立的類,進行增刪該查操做了. 進行增刪改查的操做,就是根據具體請求,經過路由模塊,到達指定的函數,而後由函數進行數據的增刪改查而後在結合模版html進行返回. 因此咱們定義對數據庫的增刪改查須要在app01/views.py中定義. 咱們在app01/urls.py中先定義一個handle_db,以下: urlpatterns = [ url(r'^home/', views.home), url(r'^handle_db/', views.handle_db), ] 而後在app01/views.py中定義handle_db函數,以下: 先小測試下: def handle_db(request): return HttpResponse('OK .....app01') 訪問http://127.0.0.1:8000/handle_db 查看返回結果是否爲OK .....app01 若是報錯,就須要檢查mysite/mysite/urls.py 文件和和app01/urls.py文件 以及settings.py文件 測試結果無問題,下面就能夠在函數中定義對數據庫的增刪改查了.咱們對數據庫操做的時候須要用到在models.py文件裏定義的類,因此要在views.py文件裏引入models文件 函數代碼以下: from app01 import models def handle_db(request): # 增 方式一 # models.UserInfo.objects.create(username='alex',password='123',age='22') # UserInfo是咱們在models中建立的類,objects是Django框架中定義必需要加的.create就是建立數據的方法 # 增 方式二 dic = {'username':'ted',"password":"123123",'age':18} models.UserInfo.objects.create(**dic) return HttpResponse('OK') 上面兩種方式方式二要注意的是傳入字典時前面加兩個** ,格式爲**dic 咱們想,實際開發中,我門要建立的數據是從哪裏來的.是否是應該是用戶在瀏覽器中輸入,經過post,或者get方式提交過來的. get方式提交的時候就是在url後面加拼接.這裏先很少說了,在模版章節中會詳細說明.咱們這裏先要知道的是,咱們在views.py中定義函數時加入的request,如def handle_db(request): request封裝了用戶的具體請求數據. 經過request.post能夠得到用戶經過post方式提交的數據 經過request.get 能夠得到用戶經過get方式提交的數據 對於Django裏基本的也是最經常使用的增刪改查代碼試例以下: def handle_db(request): # request 用戶請求的全部內容 # request.POST 獲取用戶以POST提交 # request.GET 獲取用戶以GET提交的數據 # 增 方式一 # models.UserInfo.objects.create(username='alex',password='123',age='22') # UserInfo是咱們在models中建立的類,objects是Django框架中定義必需要加的.create就是建立數據的方法 # 增 方式二 # dic = {'username':'ted',"password":"123123",'age':18} # models.UserInfo.objects.create(**dic) # 刪除 # models.UserInfo.objects.filter(username='alex').delete() # filter後面加過濾條件.不可能將全部數據都刪除 # 修改 # models.UserInfo.objects.all().update(age=10) # 查找 # models.UserInfo.objects.all() # models.UserInfo.objects.filter(age=10) # models.UserInfo.objects.filter(age=10).first() return HttpResponse('OK') 3.基本的增刪改查操做咱們會了,接下來咱們學習如何將數據和html結合起來. 首先咱們經過查詢語句得到用戶列表: def handle_db(request): user_list_obj = models.UserInfo.objects.all() #首先咱們知道這裏得到了多條數據記錄,每條數據記錄就是UserInfo類的實例 return HttpResponse('OK') 當用戶請求訪問了http://127.0.0.1:8000/app01/handle_db/,函數裏的user_list_obj是多個UserInfo 實例的列表在Django中它是一個特殊列表(queryset列表). 若是咱們想把這些數據展現到瀏覽器上.就須要: 1.把這個列表傳給html的模版 2.模版在接到數據後要對這個列表進行循環. 首先:在函數中咱們使用return HttpResponse()來返回字符串,那咱們如何返回html模版呢.這就須要用到views.py文件默認引入的render方法了. render方法的使用: def handle_db(request): user_list_obj = models.UserInfo.objects.all() #得到對象列表 return render(request,'t1.html',{'li':user_list_obj}) # render() 三個參數, # 第一個參數,request就是封裝了請求那個request. # 第二個參數,'t1.html' 模版文件的名稱. # 第三個參數,是一個字典 ,字典的key 就是模版文件中使用的變量.而user_list_obj 纔是要循環的數據列表. 結下來咱們來寫t1.html模版文件. <body> <table border="1"> <thead> <tr> <th>用戶名</th> <th>密碼</th> <th>年齡</th> </tr> </thead> <tbody> {% for item in li %} // li就是render()裏的第三個參數 字典的key,拿到這個key後,它內部實現對這個字典key對應的value進行循環 <tr> <td>{{ item.username }}</td> // jinja2裏循環裏面循環具體數據的時候用的是{{}} <td>{{ item.password }}</td> <td>{{ item.age }}</td> </tr> {% endfor %} //jinja2裏for循環結尾標記 </tbody> </table> </body> PS:Django模版默認使用python的jinja2模塊. jinja2裏規定for循環或者if else時用的標記是 {% xxxx %} 循環裏面循環具體數據時用{{}} 模版文件咱們寫好了,views.py裏函數也用rander()指定了文件和循環的數據.應該能夠在瀏覽器動態返回數據了把. no,還差一步,咱們在函數裏指定模版文件的文件名,請問函數怎麼去找到這個文件,去哪一個目錄下去找.它是如何知道呢.固然是經過settings.py配置了. 因而咱們還要一步配置settings.py TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR,'templates')], # 這裏是添加的.默認列表爲空即:[] 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] 配置完成後,就能夠訪問http://127.0.0.1:8000/app01/handle_db/,咱們在瀏覽器上就能夠看到動態表格了. 這個例子執行成功了就說明咱們理解了Django中配置app項目如何進行後臺數據抓取後配合html模版進行前端頁面展現. 此例中咱們建立的t1.html文件至關簡單,以致於很low,咱們知道想讓界面美觀須要配合上css,想要界面能夠互動,就須要使用js. 那麼咱們應該把這些css和js放到哪裏呢?它們都屬於靜態文件.因此咱們應該在mysite目錄下建立一個static目錄(和templates目錄同級),專門存放靜態文件. 而且還要在settings.py文件裏配置下靜態文件: 找到: STATIC_URL = '/static/' (這個不起做用) 在它下面加上: STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) settings.py配置完成後,就能夠在模版文件中引用了.(你會想咱們以前寫html的時候,也不須要配置啊,只是在html中直接寫引入的css路徑和js文件路徑,這裏爲何還要配置.) 緣由是,咱們是經過views.py裏的函數return給請求者的.函數裏return的是一個長字符串.因此函數在return時,函數要把html模版中引用的js文件和css文件找到並解析後返回給瀏覽器. 因此說配置settings.py其實就是告訴函數要去哪裏找這些js和css靜態文件. 而後咱們在html中就能夠引入了 <script src="/static/jquery-3.1.0.min.js"></script> //這裏看咱們引入要寫/static/xxxx.js 這樣函數纔會去settings.py裏設置的static下去找xxxx.js f.經過頁面,提交數據到後臺. 咱們知道前端經過form表單將數據提交到後臺.form標籤中有一個action,通常action指定url地址.而我們這裏有一個url:^~/app01/handle_db/, form若是提交給本地的URL,前面的IP或者域名就不須要寫了,另外若是form表單的提交方式爲post,這就牽涉到Django框架中的跨站請求.默認是拒絕提交的,那麼咱們就須要在配置中開啓. settings.py配置以下: MIDDLEWARE_CLASSES = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', #把這一行註釋掉就好了. 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] settings.py配置好後,咱們就能夠完成一個簡單的form表單代碼提交到後臺數據庫了: 首先咱們在html模版頁中加入下面的代碼 <form action="/app01/handle_db/" method="post"> <p><input type="text" name="username"/></p> <p><input type="text" name="password"/></p> <p><input type="text" name="age"/></p> <p><input type="submit" value="提交" /></p> </form> 咱們知道直接訪問url就是get方式.而點擊上面定義的form表單中的submit按鈕時纔是post提交.因此咱們在點擊提交以前是否是要經過瀏覽器請求這個頁面. 在頁面中輸入內容點擊submit的提交按鈕後,在進行post提交. 也就是說咱們訪問http://127.0.0.1:8000/app01/handle_db/時 要調用app01/views.py裏定義的handle_db函數. 當咱們在打開的頁面輸入數據後,還要在調用handle_db函數. 因此咱們要在handle_db函數中作if語句進行判斷.通常請求都是get,這時候就返回頁面.只有當請求是post時才提交數據.因而handle_db函數的代碼以下: def handle_db(request): if request.method == 'POST': # print(request.POST) 這裏是看看咱們得到的POST數據是什麼類型 # <QueryDict: {'username': [''], 'password': [''], 'age': ['']}> # 咱們看到是input裏定義的name屬性,和輸入的值.值放在列表裏. models.UserInfo.objects.create(username=request.POST['username'], password=request.POST['password'], age=request.POST['age'] ) user_list_obj = models.UserInfo.objects.all() return render(request,'t1.html',{'li':user_list_obj}) 完成這個函數後,咱們就能夠在頁面進行提交數據添加用戶名,密碼和age保存到數據庫了.本節相關知識點完結.咱們學會了 如何建立Django工程. 如何建立APP項目 如何啓動工程. django自帶的admin後臺管理功能簡述. Django提供的ORM使用介紹 路由系統的使用方法. 項目中使用ORM,完成對數據庫增刪改查的基本操做. 使用html模版,把前端和後臺數據進行關聯. 前端經過post提交數據寫入數據庫的基本使用演示.