python 全棧開發,Day88(csrf_exempt,ES6 快速入門,Vue)

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
View Code

1、csrf_exempt

在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),
]
View Code

修改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")
View Code

新增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>
View Code

訪問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()
View Code

執行輸出:

哈哈
呵呵

 

foo本來應該輸出"呵呵",可是加了裝飾器以後,輸出了2個內容。因此說,加了裝飾器以後,它就不是原來的函數了!

 

python裝飾器的wraps做用

Python裝飾器(decorator)在實現的時候,被裝飾後的函數其實已是另一個函數了(函數名等函數屬性會發生改變),爲了避免影響,Python的functools包中提供了一個叫wraps的decorator來消除這樣的反作用。寫一個decorator的時候,最好在實現以前加上functools的wrap,它能保留原有函數的名稱和docstring。

實例一:

不加wraps

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__)
View Code

執行輸出:

inner None

 

實例二:

加wraps

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__)
View Code

執行輸出:

foo
這是一個測試裝飾器的函數
:return: None

2、ES6 快速入門

快速瞭解ES6部分新特性

let和const 

let

ES6新增了let命令,用於聲明變量。其用法相似var,可是聲明的變量只在let命令所在的代碼塊內有效

{
    let x = 10;
    var y = 20;
}

x  // ReferenceError: x is not defined
y  // 20
View Code

效果以下:

var聲明變量存在變量提高。也就是在聲明變量以前就可使用該變量。

console.log(x)  // undefined,var聲明變量以前可使用該變量
var x = 10;
View Code

刷新頁面,粘貼代碼,效果以下:

而let不會這樣,let聲明的變量不能在聲明以前使用

刷新頁面,粘貼代碼,效果以下:

注意:
let不容許在相同的做用域內重複聲明同一個變量。 
好比:
function foo(){
    let x = 10;
    var x = 20;
} 
foo();  // 報錯
View Code

刷新頁面,粘貼代碼,效果以下:

 

再好比:

function foo(){
    let y = 10;
    let y = 20;
} 
foo();   // 報錯
View Code

刷新頁面,粘貼代碼,效果以下:

ES5中只有全局做用域和函數做用域,並無塊級做用域。
請看下面的示例:
var name = 'Q1mi'

function foo(){
    console.log(name)
    if (false){
        var name = 'Bob'
    }
}
foo()  // undefined
View Code

刷新頁面,粘貼代碼,效果以下:

出現上述現象的緣由就是在函數內部,因爲變量提高致使內存的name變量覆蓋了外層的name變量。
相似的狀況還出如今 for循環的計數變量最後會泄露爲全局變量。 
var聲明的變量存在變量提高,而let則不會
for (var i=0;i<5;i++){
    console.log('哈哈');
}
console.log(i);  // 5
View Code

刷新頁面,粘貼代碼,效果以下:

 

var聲明的變量會污染全局,因此在for循環外部能夠打印i的值。for循環中的i最好使用let聲明

 

ES6中的let聲明變量的方式實際上就爲JavaScript新增了塊級做用域。

var name = 'Q1mi'

function foo(){
    console.log(name)
    if (false){
        let name = 'Bob'
    }
}
foo()  // Q1mi
View Code

刷新頁面,粘貼代碼,效果以下:

此時,在foo函數內容,外層代碼塊就再也不受內層代碼塊的影響。因此相似for循環的計數變量咱們最好都是用let來聲明。

let聲明可以將變量限制在當前的塊級做用域中

 

const

const用來聲明常量。const聲明變量必須當即初始化,而且其值不能再改變。
const聲明常量的做用域與let相同,只在聲明所在的塊級做用域內有效。 
例如:
const PI = 3.14;

舉例:

const 用來聲明一個常量,不能修改

全局對象的屬性:

ES6規定:var命令和function命令聲明的全局變量依舊是全局對象的屬性;let命令、const命令和class命令聲明的全局變量不屬於全局對象的屬性。

查看下面的示例代碼:

var x = 10;
let y = 20;
window.x  // 10
window.y  // undefined
View Code

刷新頁面,粘貼代碼,效果以下:

 

 

變量的解構賦值

ES6容許按照必定的模式,從數組或對象中提取值,對變量進行賦值,這種方式被稱爲解構賦值。

var [x, y, z] = [10, 20, 30];
x;  //10
y;  //20
z;  //30
View Code

刷新頁面,粘貼代碼,效果以下:

 

對象的解構賦值:

var {x, y} = {x: 10, y: 20};
x;  // 10
y;  // 20
View Code

刷新頁面,粘貼代碼,效果以下:

 

var和function聲明的變量,默認會在windows對象上

let聲明的變量默認不會出如今windows對象上

舉例:

window.name1輸出undefined

 

字符串

include、startsWith、endsWith

在此以前,JavaScript中只有indexOf方法可用來肯定一個字符串是否包含在另外一個字符串中。

ES6中又提供了3種新方法:

includes():返回布爾值,表示是否找到了參數字符串。

stratsWith():返回布爾值,表示參數字符串是否在源字符串的開始位置。

endsWith():返回布爾值,表示參數字符串是否在源字符串的結尾位置。

示例:

var s = "Hello world!";

s.includes("o");  // true
s.startsWith("Hello");  // true
s.endsWith("!");  // true
View Code

刷新頁面,粘貼代碼,效果以下:

 

這三個方法都支持第2個參數,表示開始匹配的位置。

示例:

var s = "Hello world!";

s.includes("o", 8);  // false
s.startsWith("world", 6);  // true
s.endsWith("Hello", 5);  // true
View Code

刷新頁面,粘貼代碼,效果以下:

 

js對象的key能夠不加引號

舉例:

 

對象的解析賦值

舉例:

 

模板字符串

模板字符串(template string)是加強版的字符串,用反引號(`)標識。它能夠當作普通字符串使用,也能夠用來定義多行字符串,或者在字符串中嵌入變量。在模板字符串中嵌入變量,須要將變量名寫入${}中。

舉例:

var name = 'Q1mi', age = 18;
`My name is ${name}, I’m ${age} years old.`
View Code

刷新頁面,粘貼代碼,效果以下:

 

 

函數

箭頭函數

箭頭函數有個特色:

  1. 若是參數只有一個,能夠省略小括號
  2. 若是不寫return,能夠不寫大括號
  3. 沒有arguments變量
  4. 不改變this指向
其中箭頭函數中this指向被固定化,不是由於箭頭函數內部有綁定this的機制。實際緣由是箭頭函數根本沒有本身的this,致使內部的this就是外層代碼塊的this。
 
能夠查看下面兩段代碼輸出的區別:
var person = {
    name: 'Q1mi',
    age:18,
    func:function(){
        console.log(this);
    }
}
person.func()  // person對象
View Code

刷新頁面,粘貼代碼,效果以下:

 

var person = {
    name: 'Q1mi',
    age:18,
    func:()=>{
        console.log(this);
    }
}
person.func()  // window對象
View Code

刷新頁面,粘貼代碼,效果以下:

但凡用到箭頭函數,不要用this

 

對象 

屬性簡潔表示法

ES6容許直接寫入變量和函數做爲對象的屬性和方法。
function f(x, y){
    return {x, y}
}
View Code

上面的寫法等同於:

function f(x, y){
    return {x: x, y: y}
}
View Code

對象的方法也可使用簡潔表示法:

var o = {
    method(){
        return "hello";
    }
}
View Code

等同於:

var o = {
    method: function(){
        return "Hello";
    }
}
View Code

 刷新頁面,粘貼代碼,效果以下:

 

Object.assign() 

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
View Code

 刷新頁面,粘貼代碼,效果以下:

注意:

Object.assign方法的其餘用處,可查看文末連接。

 

面向對象

ES5的構造對象的方式 使用構造函數來創造。構造函數惟一的不一樣是函數名首字母要大寫。
構造函數,使用new關鍵字建立對象
修改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>
    // 定義一個構造函數
    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>
View Code

刷新頁面,效果以下:

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>
View Code

刷新頁面,效果以下:

 

Promise

Promise 是異步編程的一種解決方案,比傳統的解決方案(回調函數和事件)更合理、更強大。它由社區最先提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise對象。

使用Promise的優點是有了Promise對象,就能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套的回調函數。此外,Promise對象提供統一的接口,使得控制異步操做更加容易。

用法示例:

const promiseObj = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操做成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
View Code

Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolvereject。它們是兩個函數,由 JavaScript 引擎提供,不用本身部署。

Promise實例生成之後,能夠用then方法分別指定resolved狀態和rejected狀態的回調函數。

promiseObj.then(function(value) {
  // success
}, function(error) {
  // failure
});
View Code

then方法能夠接受兩個回調函數做爲參數。第一個回調函數是Promise對象的狀態變爲resolved時調用,第二個回調函數是Promise對象的狀態變爲rejected時調用。其中,第二個函數是可選的,不必定要提供。這兩個函數都接受Promise對象傳出的值做爲參數。

咱們還能夠將上面的代碼寫成下面這種方式:

promiseObj
.then(function(value) {
  // success
})
.catch(function(error) {
  // failure
});
View Code

其實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>
View Code

訪問網頁,點擊按鈕,效果以下:

 

注:

本文中的些許示例來自阮一峯的《ECMAScript 6 標準入門》

附:

想了解更多有關ES6標準內容,推薦閱讀:阮一峯的ECMAScript 6 入門

 

多讀書、多寫碼。世界很大,咱們很小。

 

3、Vue

介紹

Vue.js 是什麼

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>
View Code

直接訪問test.html頁面,效果以下:

注意:請勿使用django框架運行,由於它也是用{{ }},來表示一個變量。

因此使用django運行時,頁面是空白的!

 

咱們已經成功建立了第一個 Vue 應用!看起來這跟渲染一個字符串模板很是相似,可是 Vue 在背後作了大量工做。如今數據和 DOM 已經被創建了關聯,全部東西都是響應式的。咱們要怎麼確認呢?打開你的瀏覽器的 JavaScript 控制檯 (就在這個頁面打開),並修改 app.message 的值,你將看到上例相應地更新。

舉例:

全部的dom操做,用vue來實現了

相關文章
相關標籤/搜索