BBS項目內容回顧css
1. 登錄頁面 1. 驗證碼 1. PIL(Pillow) 2. io 2. ORM 1. 增刪改查 3. AJAX $.ajax({ url: '', type: '', data: {}, success:function(res){ console.log(res) }, error:function(err){ console.log(err) } }) 2. 註冊 1. ORM 2. form 1. 生成HTML代碼 2. 校驗(form_obj.is_valid()) 1. 局部鉤子函數 2. 全局鉤子函數 3. 保留用戶填寫的原數據,顯示報錯信息 3. AJAX var data = new FormData(); data.append(k, v) $.ajax({ url: '', type: '', processData: false, contentType: false, data: data, success:function(res){ console.log(res) }, error:function(err){ console.log(err) } }) 4. 頭像的上傳和預覽 3. BBS主頁 1. Bootstrap佈局 2. 文章列表展現 3. 自定義分頁 4. 我的站點頁面 1. 文章列表 2. 分類展現(聚合和分組, inclusion_tag) 1. 文章分類 2. 標籤分類 3. 日期歸檔 extra(select={'ym': 'DATEFORMAT(create_time, "%%Y-%%m")'}) 5. 文章詳情頁 1. 點贊 1. 事務操做 from django.db import transaction with transaction.atomic(): 語句1 語句2 2. 數據行的字段值再原來的基礎上+1 from django.db.models import F, Q 2. 評論 1. 展現評論 2. 添加評論 6. 後臺管理頁面 1. Django admin的簡單使用 2. kindeditor的使用 1. 下載按提示覆制粘貼,配置一下 2. 上傳圖片須要額外配置 3. 防XSS攻擊(BeautifulSoup4) 2. 中間件 1. 五個方法 1. process_request 2. process_views 3. process_response 4. process_exception 5. process_template_response 3. 補充 from django.views.decorators.csrf import csrf_exempt, csrf_protect csrf_exempt:指定被裝飾的視圖函數不須要校驗csrf_token csrf_protect: 指定被裝飾的視圖函數須要校驗csrf_token
在Django中對於基於函數的視圖咱們能夠 @csrf_exempt 註解來標識一個視圖能夠被跨域訪問html
對於django中設置防跨站請求僞造功能有分爲全局和局部。前端
中間件 django.middleware.csrf.CsrfViewMiddlewarevue
@csrf_protect,爲當前函數強制設置防跨站請求僞造功能,即使settings中沒有設置全局中間件。python
@csrf_exempt,取消當前函數防跨站請求僞造功能,即使settings中設置了全局中間件。jquery
注意:導入模塊git
from django.views.decorators.csrf import csrf_exempt,csrf_protect
舉例:test不校驗csrf tokenes6
修改urls.py,增長路徑github
from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('test/', views.test), ]
修改views.py,導入模塊ajax
from django.shortcuts import render,HttpResponse from django.views.decorators.csrf import csrf_exempt,csrf_protect # Create your views here. @csrf_exempt def test(request): if request.method == "POST": print(request.POST) return HttpResponse("ok") return render(request,"test.html")
新增test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> <input type="text" name="name"> <input type="submit" value="提交"> </form> </body> </html>
訪問test頁面
點擊提交,提示
中間件,能夠自定義5個方法。其中
校驗csrf_token在中間件的request_view這一層處理的
它加了一個裝飾器,那麼原來的函數,就被改變了!
舉例:
def wrapper(func): def inner(*args, **kwargs): print("哈哈") return func(*args, **kwargs) return inner @wrapper def foo(): """ 這是一個測試裝飾器的函數 :return: None """ print("呵呵") foo()
執行輸出:
哈哈
呵呵
foo本來應該輸出"呵呵",可是加了裝飾器以後,輸出了2個內容。因此說,加了裝飾器以後,它就不是原來的函數了!
Python裝飾器(decorator)在實現的時候,被裝飾後的函數其實已是另一個函數了(函數名等函數屬性會發生改變),爲了避免影響,Python的functools包中提供了一個叫wraps的decorator來消除這樣的反作用。寫一個decorator的時候,最好在實現以前加上functools的wrap,它能保留原有函數的名稱和docstring。
實例一:
def wrapper(func): def inner(*args, **kwargs): print("哈哈") return func(*args, **kwargs) return inner @wrapper def foo(): """ 這是一個測試裝飾器的函數 :return: None """ print("呵呵") # foo() print(foo.__name__, foo.__doc__)
執行輸出:
inner None
實例二:
from functools import wraps def wrapper(func): @wraps(func) def inner(*args, **kwargs): print("哈哈") return func(*args, **kwargs) return inner @wrapper def foo(): """ 這是一個測試裝飾器的函數 :return: None """ print("呵呵") # foo() print(foo.__name__, foo.__doc__)
執行輸出:
foo
這是一個測試裝飾器的函數
:return: None
快速瞭解ES6部分新特性
ES6新增了let命令,用於聲明變量。其用法相似var,可是聲明的變量只在let命令所在的代碼塊內有效。
{ let x = 10; var y = 20; } x // ReferenceError: x is not defined y // 20
效果以下:
var聲明變量存在變量提高。也就是在聲明變量以前就可使用該變量。
console.log(x) // undefined,var聲明變量以前可使用該變量
var x = 10;
刷新頁面,粘貼代碼,效果以下:
而let不會這樣,let聲明的變量不能在聲明以前使用。
刷新頁面,粘貼代碼,效果以下:
function foo(){ let x = 10; var x = 20; } foo(); // 報錯
刷新頁面,粘貼代碼,效果以下:
再好比:
function foo(){ let y = 10; let y = 20; } foo(); // 報錯
刷新頁面,粘貼代碼,效果以下:
var name = 'Q1mi' function foo(){ console.log(name) if (false){ var name = 'Bob' } } foo() // undefined
刷新頁面,粘貼代碼,效果以下:
for (var i=0;i<5;i++){ console.log('哈哈'); } console.log(i); // 5
刷新頁面,粘貼代碼,效果以下:
var聲明的變量會污染全局,因此在for循環外部能夠打印i的值。for循環中的i最好使用let聲明
ES6中的let聲明變量的方式實際上就爲JavaScript新增了塊級做用域。
var name = 'Q1mi' function foo(){ console.log(name) if (false){ let name = 'Bob' } } foo() // Q1mi
刷新頁面,粘貼代碼,效果以下:
此時,在foo函數內容,外層代碼塊就再也不受內層代碼塊的影響。因此相似for循環的計數變量咱們最好都是用let來聲明。
let聲明可以將變量限制在當前的塊級做用域中
const PI = 3.14;
舉例:
const 用來聲明一個常量,不能修改
全局對象的屬性:
ES6規定:var命令和function命令聲明的全局變量依舊是全局對象的屬性;let命令、const命令和class命令聲明的全局變量不屬於全局對象的屬性。
查看下面的示例代碼:
var x = 10; let y = 20; window.x // 10 window.y // undefined
刷新頁面,粘貼代碼,效果以下:
ES6容許按照必定的模式,從數組或對象中提取值,對變量進行賦值,這種方式被稱爲解構賦值。
var [x, y, z] = [10, 20, 30]; x; //10 y; //20 z; //30
刷新頁面,粘貼代碼,效果以下:
對象的解構賦值:
var {x, y} = {x: 10, y: 20}; x; // 10 y; // 20
刷新頁面,粘貼代碼,效果以下:
var和function聲明的變量,默認會在windows對象上
let聲明的變量默認不會出如今windows對象上
舉例:
window.name1輸出undefined
在此以前,JavaScript中只有indexOf方法可用來肯定一個字符串是否包含在另外一個字符串中。
ES6中又提供了3種新方法:
includes():返回布爾值,表示是否找到了參數字符串。
stratsWith():返回布爾值,表示參數字符串是否在源字符串的開始位置。
endsWith():返回布爾值,表示參數字符串是否在源字符串的結尾位置。
示例:
var s = "Hello world!"; s.includes("o"); // true s.startsWith("Hello"); // true s.endsWith("!"); // true
刷新頁面,粘貼代碼,效果以下:
這三個方法都支持第2個參數,表示開始匹配的位置。
示例:
var s = "Hello world!"; s.includes("o", 8); // false s.startsWith("world", 6); // true s.endsWith("Hello", 5); // true
刷新頁面,粘貼代碼,效果以下:
js對象的key能夠不加引號
舉例:
對象的解析賦值
舉例:
模板字符串(template string)是加強版的字符串,用反引號(`)標識。它能夠當作普通字符串使用,也能夠用來定義多行字符串,或者在字符串中嵌入變量。在模板字符串中嵌入變量,須要將變量名寫入${}中。
舉例:
var name = 'Q1mi', age = 18; `My name is ${name}, I’m ${age} years old.`
刷新頁面,粘貼代碼,效果以下:
箭頭函數有個特色:
var person = { name: 'Q1mi', age:18, func:function(){ console.log(this); } } person.func() // person對象
刷新頁面,粘貼代碼,效果以下:
和
var person = { name: 'Q1mi', age:18, func:()=>{ console.log(this); } } person.func() // window對象
刷新頁面,粘貼代碼,效果以下:
但凡用到箭頭函數,不要用this
function f(x, y){ return {x, y} }
上面的寫法等同於:
function f(x, y){ return {x: x, y: y} }
對象的方法也可使用簡潔表示法:
var o = { method(){ return "hello"; } }
等同於:
var o = { method: function(){ return "Hello"; } }
刷新頁面,粘貼代碼,效果以下:
Object.assign方法用來將源對象(source)的全部可枚舉屬性複製到目標對象(target)。它至少須要兩個對象做爲參數,第一個參數是目標對象,第二個參數是源對象。
參數必須都是對象,不然拋出TypeError錯誤。
Object.assjgn只複製自身屬性,不可枚舉屬性(enumerable爲false)和繼承的屬性不會被複制。
簡單示例:
var x = {name: "Q1mi", age: 18}; var y = x; var z = Object.assign({}, x); x.age = 20; x.age; // 20 y.age; // 20 z.age; // 18
刷新頁面,粘貼代碼,效果以下:
注意:
Object.assign方法的其餘用處,可查看文末連接。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> <input type="text" name="name"> <input type="submit" value="提交"> </form> <script> // 定義一個構造函數 function Point(x, y){ this.x = x; this.y = y; } // 給父級綁定方法 Point.prototype.toSting = function(){ return '(' + this.x + ',' + this.y + ')'; }; // 生成一個Point對象 var p = new Point(10, 20); console.log(p.x); console.log(p.toSting()); // 繼承 function ColorPoint(x, y, color){ Point.call(this, x, y); this.color = color; } // 繼承父類的方法 ColorPoint.prototype = Object.create(Point.prototype); // 修復 constructor ColorPoint.prototype.constructor = Point; // 擴展方法 ColorPoint.prototype.showColor = function(){ console.log('My color is ' + this.color); }; var cp = new ColorPoint(10, 20, "red"); console.log(cp.x); console.log(cp.toSting()); cp.showColor(); </script> </body> </html>
刷新頁面,效果以下:
ES6 使用Class構造對象的方式:
修改test.html,js代碼以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> <input type="text" name="name"> <input type="submit" value="提交"> </form> <script> class Point{ constructor(x, y){ this.x = x; this.y = y; } // 不要加逗號 toSting(){ return `(${this.x}, ${this.y})`; } } var p = new Point(10, 20); console.log(p.x); p.toSting(); class ColorPoint extends Point{ constructor(x, y, color){ super(x, y); // 調用父類的constructor(x, y) this.color = color; } // 不要加逗號 showColor(){ console.log('My color is ' + this.color); } } var cp = new ColorPoint(10, 20, "red"); console.log(cp.x); cp.toSting(); cp.showColor(); </script> </body> </html>
刷新頁面,效果以下:
Promise 是異步編程的一種解決方案,比傳統的解決方案(回調函數和事件)更合理、更強大。它由社區最先提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise
對象。
使用Promise的優點是有了Promise
對象,就能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套的回調函數。此外,Promise
對象提供統一的接口,使得控制異步操做更加容易。
用法示例:
const promiseObj = new Promise(function(resolve, reject) { // ... some code if (/* 異步操做成功 */){ resolve(value); } else { reject(error); } });
Promise
構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolve
和reject
。它們是兩個函數,由 JavaScript 引擎提供,不用本身部署。
Promise
實例生成之後,能夠用then
方法分別指定resolved
狀態和rejected
狀態的回調函數。
promiseObj.then(function(value) { // success }, function(error) { // failure });
then
方法能夠接受兩個回調函數做爲參數。第一個回調函數是Promise
對象的狀態變爲resolved
時調用,第二個回調函數是Promise
對象的狀態變爲rejected
時調用。其中,第二個函數是可選的,不必定要提供。這兩個函數都接受Promise
對象傳出的值做爲參數。
咱們還能夠將上面的代碼寫成下面這種方式:
promiseObj .then(function(value) { // success }) .catch(function(error) { // failure });
其實Promise.prototype.catch
方法是.then(null, rejection)
的別名,用於指定發生錯誤時的回調函數。
舉例:
修改test.html,完整代碼以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>promise 示例</h1> <button id="b1">屠龍寶刀,點擊就送!</button> <p id="p1"></p> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script> /* function foo() { $.ajax({ url: '/test/', type: 'post', data: {data: '哈哈哈'}, success:function (res) { console.log(res); return res.data $.ajax() } }) } */ function foo() { return new Promise(function (resolve, reject) { $.ajax({ url: '/test/', type: 'post', data: {data: '哈哈哈'}, success:function (res) { console.log('異步請求成功'); resolve(res.data) }, error:function (err) { console.log('異步請求失敗'); reject(err); } }) }) } $("#b1").click(function () { var promiseObj = foo(); promiseObj.then(function (value) { $("#p1").text(value); }).catch(function (err) { console.log(err) }) }) </script> </body> </html>
訪問網頁,點擊按鈕,效果以下:
注:
本文中的些許示例來自阮一峯的《ECMAScript 6 標準入門》
附:
想了解更多有關ES6標準內容,推薦閱讀:阮一峯的ECMAScript 6 入門
多讀書、多寫碼。世界很大,咱們很小。
Vue (讀音 /vjuː/,相似於 view) 是一套用於構建用戶界面的漸進式框架。與其它大型框架不一樣的是,Vue 被設計爲能夠自底向上逐層應用。Vue 的核心庫只關注視圖層,不只易於上手,還便於與第三方庫或既有項目整合。另外一方面,當與現代化的工具鏈以及各類支持類庫結合使用時,Vue 也徹底可以爲複雜的單頁應用提供驅動。
若是你想在深刻學習 Vue 以前對它有更多瞭解,咱們製做了一個視頻,帶您瞭解其核心概念和一個示例工程。
若是你已是有經驗的前端開發者,想知道 Vue 與其它庫/框架有哪些區別,請查看對比其它框架。
官方指南假設你已瞭解關於 HTML、CSS 和 JavaScript 的中級知識。若是你剛開始學習前端開發,將框架做爲你的第一步可能不是最好的主意——掌握好基礎知識再來吧!以前有其它框架的使用經驗會有幫助,但這不是必需的。
嘗試 Vue.js 最簡單的方法是使用 JSFiddle 上的 Hello World 例子。你能夠在瀏覽器新標籤頁中打開它,跟着例子學習一些基礎用法。或者你也能夠建立一個 .html
文件,而後經過以下方式引入 Vue:
<!-- 開發環境版本,包含了有幫助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
或者:
<!-- 生產環境版本,優化了尺寸和速度 --> <script src="https://cdn.jsdelivr.net/npm/vue"></script>
安裝教程給出了更多安裝 Vue 的方式。請注意咱們不推薦新手直接使用 vue-cli
,尤爲是在你還不熟悉基於 Node.js 的構建工具時。
若是你喜歡交互式的東西,你也能夠查閱這個 Scrimba 上的系列教程,它揉合了錄屏和代碼試驗田,並容許你隨時暫停和播放。
Vue.js 的核心是一個容許採用簡潔的模板語法來聲明式地將數據渲染進 DOM 的系統:
html代碼
<div id="app"> {{ message }} </div>
js代碼
var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } })
舉例:
test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="d1"> <p>{{ message }}</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#d1', data: {message: '第一個Vue示例'} }) </script> </body> </html>
直接訪問test.html頁面,效果以下:
注意:請勿使用django框架運行,由於它也是用{{ }},來表示一個變量。
因此使用django運行時,頁面是空白的!
咱們已經成功建立了第一個 Vue 應用!看起來這跟渲染一個字符串模板很是相似,可是 Vue 在背後作了大量工做。如今數據和 DOM 已經被創建了關聯,全部東西都是響應式的。咱們要怎麼確認呢?打開你的瀏覽器的 JavaScript 控制檯 (就在這個頁面打開),並修改 app.message
的值,你將看到上例相應地更新。
舉例:
全部的dom操做,用vue來實現了