django 框架練習

目錄html

常見問題相關

談談你對django的理解

1.大而全的一個web框架 採用的是MVT模式 入手簡單
2.Django的賣點是超高的開發效率,其性能擴展有限;採用Django的項目,在流量達到必定規模後,都須要對其進行重構,才能知足性能的要求。
3.Django中的ORM很是方便,作簡單的對象定義,它就能自動生成數據庫結構、以及全功能的管理後臺。
4.Django內置的ORM跟框架內的其餘模塊耦合程度高。應用程序必須使用Django內置的ORM,
5.Django適用的是中小型的網站,或者是做爲大型網站快速實現產品雛形的工具。
Django模板的設計哲學是完全的將代碼、樣式分離; Django從根本上杜絕在模板中進行編碼、處理數據的可能

django請求的生命週期?

用戶請求進來先走到  wsgi   而後將請求交給  jango的中間件   穿過django中間件(方法是process_request)  
接着就是   路由匹配   路由匹配成功以後就執行相應的    視圖函數   
在視圖函數中能夠調用orm作數據庫操做  再從模板路徑   將模板拿到   而後在後臺進行模板渲染   
模板渲染完成以後就變成一個字符串     再把這個字符串通過全部中間件(方法:process_response)  和wsgi 返回給用戶

img

簡述MVC和MTV

MVC:model 模型、view(視圖)、controller(控制器)
MTV:model、tempalte、view

列舉django的內置組件?

.Admin是對model中對應的數據表進行增刪改查提供的組件
.model組件:負責操做數據庫
.form組件:1.生成HTML代碼2.數據有效性校驗3校驗信息返回並展現
.ModelForm組件即用於數據庫操做,也可用於用戶請求的驗證

django的request對象是在何時建立的?

當請求一個頁面時, Django會創建一個包含請求元數據的 HttpRequest 對象. 
當Django 加載對應的視圖時, HttpRequest對象將做爲視圖函數的第一個參數. 
每一個視圖會返回一個HttpResponse對象.

談談你對websocket協議的認識。

websocket是給瀏覽器新建的一套(相似與http)協議,協議規定:(\r\n分割)瀏覽器和服務器鏈接以後不斷開,
    以此完成:服務端向客戶端主動推送消息。

websocket協議額外作的一些操做
握手  ---->  鏈接錢進行校驗
加密  ----> payload_len=127/126/<=125   --> mask key 


本質
建立一個鏈接後不斷開的socket
當鏈接成功以後:
    客戶端(瀏覽器)會自動向服務端發送消息,包含: Sec-WebSocket-Key: iyRe1KMHi4S4QXzcoboMmw==
    服務端接收以後,會對於該數據進行加密:base64(sha1(swk + magic_string))
    構造響應頭:
            HTTP/1.1 101 Switching Protocols\r\n
            Upgrade:websocket\r\n
            Connection: Upgrade\r\n
            Sec-WebSocket-Accept: 加密後的值\r\n
            WebSocket-Location: ws://127.0.0.1:8002\r\n\r\n        
    發給客戶端(瀏覽器)
創建:雙工通道,接下來就能夠進行收發數據
    發送數據是加密,解密,根據payload_len的值進行處理
        payload_len <= 125
        payload_len == 126
        payload_len == 127
    獲取內容:
        mask_key
        數據
        根據mask_key和數據進行位運算,就能夠把值解析出來。

什麼是magic string

客戶端向服務端發送消息時,會有一個'sec-websocket-key'和'magic string'的隨機字符串(魔法字符串)
# 服務端接收到消息後會把他們鏈接成一個新的key串,進行編碼、加密,確保信息的安全性

django、flask、tornado框架的比較?

django
    大而全的框架它的內部組件比較多,內部提供:ORM、Admin、中間件、Form、ModelForm、Session、
緩存、信號、CSRF;功能也都挺完善的

flask
,微型框架,內部組件就比較少了,可是有不少第三方組件來擴展它,
  好比說有那個wtform(與django的modelform相似,表單驗證)、flask-sqlalchemy(操做數據庫的)、
  flask-session、flask-migrate、flask-script、blinker可擴展強,第三方組件豐富。因此對他自己來講有那種短小精悍的感受
- tornado,異步非阻塞。

django和flask的共同點就是,他們2個框架都沒有寫socket,因此他們都是利用第三方模塊wsgi。
可是內部使用的wsgi也是有些不一樣的:django自己運行起來使用wsgiref,而flask使用werkzeug wsgi
還有一個區別就是他們的請求管理不太同樣:django是經過將請求封裝成request對象,再經過參數傳遞,而flask是經過上下文管理機制

Tornado
是一個輕量級的Web框架,異步非阻塞+內置WebSocket功能。
'目標':經過一個線程處理N個併發請求(處理IO)。
內部組件
    #內部本身實現socket
    #路由系統
    #視圖
  #模板
   #cookie
    #csrf

django如何實現websocket?

django中能夠經過channel實現websocket

django緩存如何設置?

jango中提供了6種緩存方式:
  開發調試(不加緩存)
  內存
  文件
  數據庫
  Memcache緩存(python-memcached模塊)
  Memcache緩存(pylibmc模塊)

安裝第三方組件支持redis:
  django-redis組件


設置緩存
# 全站緩存(中間件)
MIDDLEWARE_CLASSES = (
    ‘django.middleware.cache.UpdateCacheMiddleware’, #第一
    'django.middleware.common.CommonMiddleware',
    ‘django.middleware.cache.FetchFromCacheMiddleware’, #最後
)
 
# 視圖緩存
from django.views.decorators.cache import cache_page
import time
  
@cache_page(15)          #超時時間爲15秒
def index(request):
   t=time.time()      #獲取當前時間
   return render(request,"index.html",locals())
 
# 模板緩存
{% load cache %}
 <h3 style="color: green">不緩存:-----{{ t }}</h3>
  
{% cache 2 'name' %} # 存的key
 <h3>緩存:-----:{{ t }}</h3>
{% endcache %}

django的緩存能使用redis嗎?若是能夠的話,如何配置?

pip install django-redis  
  apt-get install redis-serv

在setting添加配置文件
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache", # 緩存類型
        "LOCATION": "127.0.0.1:6379", # ip端口
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",  #
            "CONNECTION_POOL_KWARGS": {"max_connections": 100} # 鏈接池最大鏈接數
            # "PASSWORD": "密碼",
        }
    }
}


使用
from django.shortcuts import render,HttpResponse
from django_redis import get_redis_connection
  
def index(request):
# 根據名字去鏈接池中獲取鏈接
conn = get_redis_connection("default")
    conn.hset('n1','k1','v1') # 存數據
    return HttpResponse('...')

什麼是同源和跨域

同源:域名、協議、端口徹底相同。
跨域:域名、協議、端口有其中的同樣不一樣。
什麼是同源策略
同協議、同domain(或ip)、同端口,視爲同一個域,一個域內的腳本僅僅具備本域內的權限。
理解:本域腳本只能讀寫本域內的資源,而沒法訪問其它域的資源。這種安全限制稱爲同源策略。  
前端解決跨域訪問的經常使用方式
  1.jsonp
  2.iframe 元素會建立包含另一個文檔的內聯框架(即行內框架)
  3.代理:如vue-cli項目中的config/index.js文件中的proxyTable設置所要跨域訪問的地址
  
ors跨域(場景:先後端分離時,本地測試開發時使用)
若是網站之間存在跨域,域名不一樣,端口不一樣會致使出現跨域,但凡出現跨域,瀏覽器就會出現同源策略的限制
解決:在咱們的服務端給咱們響應數據,加上響應頭---> 在中間件加的

設想這樣一種狀況:A網站是一家銀行,用戶登陸之後,又去瀏覽其餘網站。若是其餘網站能夠讀取A網站的 Cookie,會發生什麼?


很顯然,若是 Cookie 包含隱私(好比存款總額),這些信息就會泄漏。更可怕的是,Cookie 每每用來保存用戶的登陸狀態,若是用戶沒有退出登陸,其餘網站就能夠冒充用戶,隨心所欲。由於瀏覽器同時還規定,提交表單不受同源政策的限制。

因而可知,"同源政策"是必需的,不然 Cookie 能夠共享,互聯網就毫無安全可言了。

  https://www.cnblogs.com/kiscon/p/8633076.html

HTTP相關

列舉Http請求中的狀態碼?

分類:
1**  信息,服務器收到請求,須要請求者繼續執行操做
2**  成功,操做被成功接收並處理
3** 重定向,須要進一步的操做以完成請求
4** 客戶端錯誤,請求包含語法錯誤或沒法完成請求
5** 服務器錯誤,服務器在處理請求的過程當中發生了錯誤

常見的狀態碼
200 -請求成功
202 -已接受請求,還沒有處理
204 -請求成功,且不需返回內容
301 - 資源(網頁等)被永久轉移到其餘url
400 - 請求的語義或是參數有錯
403 - 服務器拒絕請求
404 - 請求資源(網頁)不存在

500 - 內部服務器錯誤
502 - 網關錯誤,通常是服務器壓力過大致使鏈接超時
503 - 因爲超載或系統維護,服務器暫時的沒法處理客戶端的請求。

列舉Http請求中常見的請求頭?

- user-agent這個頭信息識別發出請求的瀏覽器或其餘客戶端,並能夠向不一樣類型的瀏覽器返回不一樣的內容。

- host這個頭信息指定原始的 URL 中的主機和端口。

- referer  
    這個頭信息指示所指向的 Web 頁的 URL。例如,若是您在網頁 1,點擊一個連接到網頁 2,當瀏覽器請求網頁 2 時,網頁 1 的 URL 就會包含在    Referer 頭信息中。
    
- cookie 這個頭信息把以前發送到瀏覽器的 cookies 返回到服務器。
- content-type

Http和Https的區別?

#Http: 80端口
#https: 443端口
# http信息是明文傳輸,https則是具備安全性的ssl加密傳輸協議。
#- 自定義證書 
    - 服務端:建立一對證書
    - 客戶端:必須攜帶證書
#- 購買證書
    - 服務端: 建立一對證書,。。。。
    - 客戶端: 去機構獲取證書,數據加密後發給我們的服務單
    - 證書機構:公鑰給改機構

wsgi相關

1.什麼是wsgi、uwsgi、uWSGI

WSGI:
web服務器網關接口,是一套協議。用於接收用戶請求並將請求進行初次封裝,而後將請求交給web框架
實現wsgi協議的模塊:
1. wsgiref,本質上就是編寫一個socket服務端,用於接收用戶請求(django)
2.werkzeug,本質上就是編寫一個socket服務端,用於接收用戶請求(flask)
uwsgi:
與WSGI同樣是一種通訊協議,它是uWSGI服務器的獨佔協議,用於定義傳輸信息的類型
uWSGI:
是一個web服務器,實現了WSGI協議,uWSGI協議,http協議,

中間件相關

1.列舉django中間件的5個方法?

process_request : 請求進來時,權限認證

process_view : 路由匹配以後,可以獲得視圖函數

process_exception : 異常時執行

process_template_responseprocess : 模板渲染時執行

process_response : 請求有響應時執行

url相關

django路由系統中name的做用?

反向解析路由字符串
路由系統中name的做用:反向解析
url(r'^home', views.home, name='home')
在模板中使用:{ % url 'home' %}
在視圖中使用:reverse(「home」)

當後期要修改url設置規則時,在不使用name字段的時候,不但要修改urls.py文件中的url路由,還要講html文件中全部的相同路徑進行修改,在實際應用中將會有大量的url路由,這樣修改下來將會十分的麻煩。
可是,若是使用name字段只須要在urls.py 文件中將path()中的url路由修改了就好了,html文件中的則不須要修改,由於這種方式下是經過name字段來映射url的,故不用再去修改html文件了。而通常狀況下name的值又是不會變化的,故後期修改起來將會十分的方便。

命名空間

即便不一樣的APP使用相同的URL名稱,URL的命名空間模式也可讓你惟一反轉命名的URL。

視圖相關

什麼是FBV和CBV

FBV和CBV本質是同樣的
基於函數的視圖叫作FBV,基於類的視圖叫作CBV
在python中使用CBV的優勢:

cbv的好處
提升了代碼的複用性,可使用面嚮對象的技術,好比Mixin(多繼承)
能夠用不一樣的函數針對不一樣的HTTP方法處理,而不是經過不少 if 判斷,提升代碼可讀性

如何給CBV的程序添加裝飾器?

第一步先引入模塊from django.utils.decorators import method_decorator`
第2步 加語法糖@method_decorator(wrapper)`


from django.shortcuts import render,HttpResponse
from django.views import View
from django.utils.decorators import method_decorator
def wrapper(func):
    def inner(*args, **kwargs):
        print(11111)
        ret = func(*args, **kwargs)
        print(22222)
        return ret
    return inner

# @method_decorator(wrapper,name='get')  # 方式3給get加 用的很少
class LoginView(View):

    @method_decorator(wrapper)  #方式1
    def get(self,request):
        print('小小小小')
        return HttpResponse('登陸成功')

    def post(self,request):
        print(request.POST)
        return HttpResponse('登陸成功')

FBV與CBV的區別

- 沒什麼區別,由於他們的本質都是函數。CBV的.as_view()返回的view函數,view函數中調用類的dispatch方法,
在dispatch方法中經過反射執行get/post/delete/put等方法。D

非要說區別的話:
- CBV比較簡潔,GET/POST等業務功能分別放在不一樣get/post函數中。FBV本身作判斷進行區分。

request 對象 的常見方法 HTTPResponse 對象

request.method    ——》 請求的方式 8種  GET POST PUT DELETE OPTIONS
        request.GET       ——》 字典  url上攜帶的參數
        request.POST      ——》 字典  form表單經過POST請求提交的數據
        request.path_info ——》 URL路徑 不帶參數 
        request.body      ——》 請求體
        request.FILES       上傳的文件  {}
        request.COOKIES     cookie
        request.session     session
        request.META            請求頭
        
redirect 重定向
def cs(request):
    return redirect('/cs1/')  #重定向到url爲cs1的地址

def cs1(request):
    return HttpResponse('666') #返回字符串666
    
def cs1(request):
    render(request,'xx.html')#返回html頁面

ORM相關

列舉django orm 中全部的方法(QuerySet對象的全部方法)

返回QuerySet對象的方法有:
      all()所有
      filter()過濾
      exclude() 排除的意思
      order_by() 
      reverse() queryset類型的數據來調用,對查詢結果反向排序,
      distinct()    values和values_list獲得的queryset類型的數據來調用,從返回結果中剔除重複紀錄 去重
  特殊的QuerySet:
      values()       返回一個可迭代的字典序列
      values_list() 返回一個可迭代的元組序列
  返回具體對象的:
      get() 
      first()第一個
      last()最後一個
  返回布爾值的方法有:
      exists() queryset類型的數據來調用,若是QuerySet包含數據,就返回True,不然返回False
  返回數字的方法有:
      count() 
      
      
    model對象能夠點出來 queryset對象相互轉換  只要是返回的queryset類型,就能夠繼續鏈式調用queryset類型的其餘的查找方法,其餘方法也是同樣的

<1> all():                  查詢全部結果,結果是queryset類型
  查詢全部的數據  .all方法 返回的是queryset集合
    all_objs = models.Student.objects.all()  # 相似於列表  --  queryset集合
    for i in all_objs:
         print(i.name)
    print(all_objs)
    
    
    
<2> filter(**kwargs):       它包含了與所給篩選條件相匹配的對象,結果也是queryset類型 Book.objects.filter(title='linux',price=100) #裏面的多個條件用逗號分開,而且這幾個條件必須都成立,是and的關係,
    models.Student.objects.all().filter(id=7)  queryset類型能夠調用fitler在過濾
  

<3> get(**kwargs):          返回與所給篩選條件相匹配的對象,不是queryset類型,是行記錄對象,返回結果有且只有一個,
                            若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。捕獲異常try。  Book.objects.get(id=1)
  
<4> exclude(**kwargs):      排除的意思,它包含了與所給篩選條件不匹配的對象,沒有不等於的操做昂,用這個exclude,返回值是queryset類型 Book.objects.exclude(id=6),返回id不等於6的全部的對象,或者在queryset基礎上調用,Book.objects.all().exclude(id=6)
    exclude(**kwargs): 排除,objects控制器和queryset集合均可以調用,返回結果是queryset類型
    query = models.Student.objects.exclude(id=1)
    print(query)
    query = models.Student.objects.filter(age=38).exclude(id=6)
    print(query)
                 
<5> order_by(*field): 排序      queryset類型的數據來調用,對查詢結果排序,默認是按照id來升序排列的,返回值仍是queryset類型
                  models.Book.objects.all().order_by('price','id') #直接寫price,默認是按照price升序排列,按照字段降序排列,就寫個負號就好了order_by('-cs'),order_by('price','id')是多條件排序,按照price進行升序,price相同的數據,按照id進行升序
        
        
<6> reverse():              queryset類型的數據來調用,對查詢結果反向排序,返回值仍是queryset類型
            # 只能夠排序以後反轉
            # query = models.Student.objects.all().order_by('id').reverse()
            # print(query)

<7> count():       queryset類型的數據來調用,返回數據庫中匹配查詢(QuerySet)的對象數量。
  
<8> first():    queryset類型的數據來調用 ,返回第一條記錄結果爲model對象類型 Book值    
  
<9> last():                queryset類型的數據來調用,返回最後一條記錄,結果爲model對象類型
  
<10> exists():              queryset類型的數據來調用,若是QuerySet包含數據,就返回True,不然返回False
                   空的queryset類型數據也有布爾值True和False,可是通常不用它來判斷數據庫裏面是否是有數據,若是有大量的數據,你用它來判斷,那麼就須要查詢出全部的數據,效率太差了,用count或者exits
                 例:all_books = models.Book.objects.all().exists() #翻譯成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是經過limit 1,取一條來看看是否是有數據

<11> values(*field):        用的比較多,queryset類型的數據來調用,返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列
                            model的實例化對象,而是一個可迭代的字典序列,只要是返回的queryset類型,就能夠繼續鏈式調用queryset類型的其餘的查找方法,其餘方法也是同樣的。 裏面能夠加子段顯示
        
<12> values_list(*field):   它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 裏面能夠加子段顯示
 
<13> distinct():            values和values_list獲得的queryset類型的數據來調用,從返回結果中剔除重複紀錄 去重,結果仍是queryset 裏面不能夠傳參 顯示nanme等等能夠用來去重
    query = models.Student.objects.all().values('age').distinct()
    print(query)

filter和exclude的區別?

def filter(self, *args, **kwargs)
      # 條件查詢(符合條件)
       # 查出符合條件
      # 條件能夠是:參數,字典,Q

  def exclude(self, *args, **kwargs)
      # 條件查詢(排除條件)
      # 排除不想要的
      # 條件能夠是:參數,字典,Q

列舉django orm中三種能寫sql語句的方法。

1.使用execute執行自定義的SQL
     直接執行SQL語句(相似於pymysql的用法)
        # 更高靈活度的方式執行原生SQL語句
        from django.db import connection
        cursor = connection.cursor()
        cursor.execute("SELECT DATE_FORMAT(create_time, '%Y-%m') FROM blog_article;")
        ret = cursor.fetchall()
        print(ret)
2.使用extra方法 :queryset.extra(select={"key": "原生的SQL語句"})


3.使用raw()方法
    1.執行原始sql並返回模型
    2.依賴model多用於查詢

F和Q的做用?

F:主要用來獲取原數據進行計算。 同表 字段比較 更新)
  Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。
  修改操做也可使用F函數,好比將每件商品的價格都在原價格的基礎上增長10
from django.db.models import F
from app01.models import Goods
 
Goods.objects.update(price=F("price")+10)  # 對於goods表中每件商品的價格都在原價格的基礎上增長10元
F查詢專門對對象中某列值的操做,不可以使用__雙下劃線!


Q:用來進行復雜查詢 Q查詢(與或非)
    Q查詢能夠組合使用 「&」, 「|」 操做符,當一個操做符是用於兩個Q的對象,它產生一個新的Q對象,
  Q對象能夠用 「~」 操做符放在前面表示否認,也可容許否認與不否認形式的組合。
  Q對象能夠與關鍵字參數查詢一塊兒使用,不過必定要把Q對象放在關鍵字參數查詢的前面。

  Q(條件1) | Q(條件2) 或
  Q(條件1) & Q(條件2) 且
  Q(條件1) & ~Q(條件2) 非

如何使用django orm批量建立數據?

def bulk_create(self, objs, batch_size=None):
    # 批量插入
    # batch_size表示一次插入的個數
    objs = [
        models.DDD(name='r11'),
        models.DDD(name='r22')
    ]
    models.DDD.objects.bulk_create(objs, 10)

only和defer的區別?

def defer(self, *fields):
    models.UserInfo.objects.defer('username','id')
    或
    models.UserInfo.objects.filter(...).defer('username','id')
    #映射中排除某列數據

 def only(self, *fields):
    #僅取某個表中的數據
     models.UserInfo.objects.only('username','id')
     或
     models.UserInfo.objects.filter(...).only('username','id')

filter和exclude的區別?

def filter(self, *args, **kwargs)
      # 條件查詢(符合條件)
       # 查出符合條件
      # 條件能夠是:參數,字典,Q

  def exclude(self, *args, **kwargs)
      # 條件查詢(排除條件)
      # 排除不想要的
      # 條件能夠是:參數,字典,Q

django orm 中如何設置讀寫分離?

方式一:手動使用queryset的using方法
from django.shortcuts import render,HttpResponse
from app01 import models
def index(request):

    models.UserType.objects.using('db1').create(title='普通用戶')
  # 手動指定去某個數據庫取數據
    result = models.UserType.objects.all().using('db1')
    print(result)

    return HttpResponse('...')

方式二:寫配置文件
class Router1:
  #  指定到某個數據庫取數據
    def db_for_read(self, model, **hints):
        """
        Attempts to read auth models go to auth_db.
        """
        if model._meta.model_name == 'usertype':
            return 'db1'
        else:
            return 'default'
   # 指定到某個數據庫存數據
    def db_for_write(self, model, **hints):
        """
        Attempts to write auth models go to auth_db.
        """
        return 'default'
再寫到配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'db1': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
DATABASE_ROUTERS = ['db_router.Router1',]

values和values_list的區別?

def values(self, *fields):
    # 獲取每行數據爲字典格式

def values_list(self, *fields, **kwargs):
    # 獲取每行數據爲元祖

如何使用django orm批量建立數據?

obj_list裏面是列表 列表裏有對象
models.Book.objects.bulk_create(obj_list)  #批量建立

django中如何實現orm表中添加數據時建立一條日誌記錄。

使用django的信號機制,能夠在添加、刪除數據先後設置日誌記錄
pre_init  # Django中的model對象執行其構造方法前,自動觸發
post_init  # Django中的model對象執行其構造方法後,自動觸發
pre_save  # Django中的model對象保存前,自動觸發
post_save  # Django中的model對象保存後,自動觸發
pre_delete  # Django中的model對象刪除前,自動觸發
post_delete  # Django中的model對象刪除後,自動觸發

解釋orm中 db first 和 code first的含義?

db first: 先建立數據庫,再更新表模型
code first:先寫表模型,再更新數據庫
https://www.cnblogs.com/jassin-du/p/8988897.html

django中如何根據數據庫表生成model中的類?

一、修改seting文件,在setting裏面設置要鏈接的數據庫類型和名稱、地址
二、運行下面代碼能夠自動生成models模型文件
       - python manage.py inspectdb
三、建立一個app執行下下面代碼:
       - python manage.py inspectdb > app/models.py

使用orm和原生sql的優缺點?

SQL:
# 優勢:
執行速度快
# 缺點:
編寫複雜,開發效率不高
---------------------------------------------------------------------------
ORM:
# 優勢:
讓用戶再也不寫SQL語句,提升開發效率
能夠很方便地引入數據緩存之類的附加功能
# 缺點:
在處理多表聯查、where條件複雜查詢時,ORM的語法會變得複雜。
沒有原生SQL速度快

模板相關

django中csrf的實現機制?

目的:防止用戶直接向服務端發起POST請求
- 用戶先發送GET獲取csrf token: Form表單中一個隱藏的標籤 + token
- 發起POST請求時,須要攜帶以前發送給用戶的csrf token;
- 在中間件的process_view方法中進行校驗。

在html中添加{%csrf_token%}標籤

django的模板中filter和simple_tag的區別?

filter : 相似管道,只能接受兩個參數第一個參數是|前的數據

simple_tag : 相似函數
一、模板繼承:{ % extends 'layouts.html' %}
二、自定義方法
    'filter':只能傳遞兩個參數,能夠在if、for語句中使用
    'simple_tag':能夠無線傳參,不能在if for中使用
    'inclusion_tags':可使用模板和後端數據
三、防xss攻擊: '|safe'、'mark_safe'

組件相關

django的Form和ModeForm的做用?

- 做用:
      - 對用戶請求數據格式進行校驗
      - 自動生成HTML標籤
  - 區別:
      - Form,字段須要本身手寫。
          class Form(Form):
              xx = fields.CharField(.)
              xx = fields.CharField(.)
              xx = fields.CharField(.)
              xx = fields.CharField(.)
      - ModelForm,能夠經過Meta進行定義
          class MForm(ModelForm):
              class Meta:
                  fields = "__all__"
                  model = UserInfo                            
  - 應用:只要是客戶端向服務端發送表單數據時,均可以進行使用,如:用戶登陸註冊

django的Form組件中,若是字段中包含choices參數,請使用兩種方式實現數據源實時更新。

方式一:重寫構造方法,在構造方法中從新去數據庫獲取值
  class UserForm(Form):
      name = fields.CharField(label='用戶名',max_length=32)
      email = fields.EmailField(label='郵箱')
      ut_id = fields.ChoiceField(
          # choices=[(1,'普通用戶'),(2,'IP用戶')]
          choices=[]
      )

      def __init__(self,*args,**kwargs):
          super(UserForm,self).__init__(*args,**kwargs)

          self.fields['ut_id'].choices = models.UserType.objects.all().values_list('id','title')
  
方式二: ModelChoiceField字段
  from django.forms import Form
  from django.forms import fields
  from django.forms.models import ModelChoiceField
  class UserForm(Form):
      name = fields.CharField(label='用戶名',max_length=32)
      email = fields.EmailField(label='郵箱')
      ut_id = ModelChoiceField(queryset=models.UserType.objects.all())    

  依賴:
      class UserType(models.Model):
          title = models.CharField(max_length=32)

          def __str__(self):
              return self.title

django的Model中的ForeignKey字段中的on_delete參數有什麼做用?

在django2.0後,定義外鍵和一對一關係的時候須要加on_delete選項,此參數爲了不兩個表裏的數據不一致問題,否則會報錯:

TypeError: __init__() missing 1 required positional argument: 'on_delete'

 舉例說明:

user=models.OneToOneField(User)

owner=models.ForeignKey(UserProfile)

須要改爲:

user=models.OneToOneField(User,on_delete=models.CASCADE)          --在老版本這個參數(models.CASCADE)是默認值

owner=models.ForeignKey(UserProfile,on_delete=models.CASCADE)    --在老版本這個參數(models.CASCADE)是默認值
參數說明:

on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五個可選擇的值

CASCADE:此值設置,是級聯刪除。
PROTECT:此值設置,是會報完整性錯誤。
SET_NULL:此值設置,會把外鍵設置爲null,前提是容許爲null。
SET_DEFAULT:此值設置,會把設置爲外鍵的默認值。
SET():此值設置,會調用外面的值,能夠是一個函數。
通常狀況下使用CASCADE就能夠了。

django的contenttype組件的做用?

contenttype是django的一個組件(app),它能夠將django下全部app下的表記錄下來
可使用他再加上表中的兩個字段,實現一張表和N張表動態建立FK關係。
   - 字段:表名稱
   - 字段:數據行ID
應用:路飛表結構優惠券和專題課和學位課關聯

ajax相關

什麼是ajax請求?並使用jQuery和XMLHttpRequest對象實現一個ajax請求。

基於django使用ajax發送post請求時,均可以使用哪一種方法攜帶csrf token?

//方式一給每一個ajax都加上上請求頭
    function Do1(){
        $.ajax({
            url:"/index/",
            data:{id:1},
            type:'POST',
       data:{csrfmiddlewaretoken:'{{ csrf_token }}',name:'alex'}
            success:function(data){
                console.log(data);
            }
        });
    }

方式二:須要先下載jQuery-cookie,才能去cookie中獲取token
        function Do1(){
        $.ajax({
            url:"/index/",
            data:{id:1},
            type:'POST',
            headers:{
              'X-CSRFToken':$.cookie('csrftoken')  // 去cookie中獲取
            },
            success:function(data){
                console.log(data);
            }
        });
    }

方式三:搞個函數ajaxSetup,當有多的ajax請求,即會執行這個函數
        $.ajaxSetup({
           beforeSend:function (xhr,settings) {
               xhr.setRequestHeader("X-CSRFToken",$.cookie('csrftoken'))
           } 
        });

函數版本
<body>
<input type="button" onclick="Do1();"  value="Do it"/>
<input type="button" onclick="Do2();"  value="Do it"/>
<input type="button" onclick="Do3();"  value="Do it"/>

<script src="/static/jquery-3.3.1.min.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
        }
    });

     function Do1(){
        $.ajax({
            url:"/index/",
            data:{id:1},
            type:'POST',
            success:function(data){
                console.log(data);
            }
        });
    }

     function Do2(){
        $.ajax({
            url:"/index/",
            data:{id:1},
            type:'POST',
            success:function(data){
                console.log(data);
            }
        });
    }

     function Do3(){
        $.ajax({
            url:"/index/",
            data:{id:1},
            type:'POST',
            success:function(data){
                console.log(data);
            }
        });
    }
</script>
</body>

vue相關

vue中的路由的攔截器的做用?

vue-resource的interceptors攔截器的做用正是解決此需求的妙方。
在每次http的請求響應以後,若是設置了攔截器以下,會優先執行攔截器函數,獲取響應體,而後纔會決定是否把response返回給then進行接收

列舉vue的常見指令。

一、v-if指令:判斷指令,根據表達式值得真假來插入或刪除相應的值。
  二、v-show指令:條件渲染指令,不管返回的布爾值是true仍是false,元素都會存在在html中,只是false的元素會隱藏在html中,並不會刪除.
  三、v-else指令:配合v-if或v-else使用。
  四、v-for指令:循環指令,至關於遍歷。
  五、v-bind:給DOM綁定元素屬性。
  六、v-on指令:監聽DOM事件。

先後端分離

談談你對restfull 規範的認識?

restful其實就是一套編寫接口的'協議',規定如何編寫以及如何設置返回值、狀態碼等信息。
# 最顯著的特色:
# 用restful: 
    給用戶一個url,根據method不一樣在後端作不一樣的處理
    好比:post建立數據、get獲取數據、put和patch修改數據、delete刪除數據。
# 不用restful: 
    給調用者不少url,每一個url表明一個功能,好比:add_user/delte_user/edit_user/
# 固然,還有協議其餘的,好比:
    '版本'來控制讓程序有多個版本共存的狀況,版本能夠放在 url、請求頭(accept/自定義)、GET參數
    '狀態碼'200/300/400/500
    'url中儘可能使用名詞'restful也能夠稱爲「面向資源編程」
    'api標示'
        api.luffycity.com
        www.luffycity.com/api/

接口的冪等性是什麼意思?

'一個接口經過1次相同的訪問,再對該接口進行N次相同的訪問時,對資源不造影響就認爲接口具備冪等性。'
    GET,  #第一次獲取結果、第二次也是獲取結果對資源都不會形成影響,冪等。
    POST, #第一次新增數據,第二次也會再次新增,非冪等。
    PUT,  #第一次更新數據,第二次不會再次更新,冪等。
    PATCH,#第一次更新數據,第二次不會再次更新,非冪等。
    DELTE,#第一次刪除數據,第二次不在再刪除,冪等。

什麼是RPC?

'遠程過程調用協議'
是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。
進化的順序: 現有的RPC,而後有的RESTful規範

爲何要使用django rest framework框架?

# 在編寫接口時能夠不使用django rest framework框架,
# 不使用:也能夠作,能夠用django的CBV來實現,開發者編寫的代碼會更多一些。
# 使用:內部幫助咱們提供了不少方便的組件,咱們經過配置就能夠完成相應操做,如:
    '序列化'能夠作用戶請求數據校驗+queryset對象的序列化稱爲json
    '解析器'獲取用戶請求數據request.data,會自動根據content-type請求頭的不能對數據進行解析
    '分頁'將從數據庫獲取到的數據在頁面進行分頁顯示。
     # 還有其餘組件:
         '認證'、'權限'、'訪問頻率控制

django rest framework框架中都有那些組件?

#- 路由,自動幫助開發者快速爲一個視圖建立4個url
        www.oldboyedu.com/api/v1/student/$
        www.oldboyedu.com/api/v1/student(?P<format>\w+)$
        www.oldboyedu.com/api/v1/student/(?P<pk>\d+)/$
        www.oldboyedu.com/api/v1/student/(?P<pk>\d+)(?P<format>\w+)$
#- 版本處理
    - 問題:版本均可以放在那裏?
            - url
            - GET 
            - 請求頭 
#- 認證 
    - 問題:認證流程?
#- 權限 
    - 權限是否能夠放在中間件中?以及爲何?
#- 訪問頻率的控制
    匿名用戶能夠真正的防止?沒法作到真正的訪問頻率控制,只能把小白拒之門外。
    若是要封IP,使用防火牆來作。
    登陸用戶能夠經過用戶名做爲惟一標示進行控制,若是有人註冊不少帳號,則沒法防止。
#- 視圖
#- 解析器 ,根據Content-Type請求頭對請求體中的數據格式進行處理。request.data 
#- 分頁
#- 序列化
    - 序列化
        - source
        - 定義方法
    - 請求數據格式校驗
#- 渲染器

django rest framework框架中的視圖均可以繼承哪些類

a. 繼承APIView(最原始)但定製性比較強
    這個類屬於rest framework中的頂層類,內部幫助咱們實現了只是基本功能:認證、權限、頻率控制,
但凡是數據庫、分頁等操做都須要手動去完成,比較原始。
    class GenericAPIView(APIView)
    def post(...):
          pass 

b.繼承GenericViewSet(ViewSetMixin,generics.GenericAPIView)
  首先他的路由就發生變化
    若是繼承它以後,路由中的as_view須要填寫對應關係
  在內部也幫助咱們提供了一些方便的方法:
  get_queryset
  get_object
  get_serializer
  get_serializer_class
  get_serializer_context
  filter_queryset
注意:要設置queryset字段,不然會拋出斷言的異常。

代碼
只提供增長功能 只繼承GenericViewSet

class TestView(GenericViewSet):
  serialazer_class = xxx
  def creat(self,*args,**kwargs):
    pass  # 獲取數據並對數據

c. 繼承  modelviewset  --> 快速快發
    -ModelViewSet(增刪改查全有+數據庫操做)
    -mixins.CreateModelMixin(只有增),GenericViewSet
    -mixins.CreateModelMixin,DestroyModelMixin,GenericViewSet
  對數據庫和分頁等操做不用咱們在編寫,只須要繼承相關類便可。
  
示例:只提供增長功能
class TestView(mixins.CreateModelMixin,GenericViewSet):
    serializer_class = XXXXXXX
*** 
  modelviewset --> 快速開發,複雜點的genericview、apiview

簡述 django rest framework框架的認證流程。

- 如何編寫?寫類並實現authenticators
  請求進來認證須要編寫一個類,類裏面有一個authenticators方法,咱們能夠自定義這個方法,能夠定製3類返回值。
  成功返回元組,返回none爲匿名用戶,拋出異常爲認證失敗。

源碼流程:請求進來先走dispatch方法,而後封裝的request對象會執行user方法,由user觸發authenticators認證流程
- 方法中能夠定義三種返回值:
    - (user,auth),認證成功
    - None , 匿名用戶
    - 異常 ,認證失敗
- 流程:
    - dispatch 
    - 再去request中進行認證處理

django rest framework如何實現的用戶訪問頻率控制?

# 對匿名用戶,根據用戶IP或代理IP做爲標識進行記錄,爲每一個用戶在redis中建一個列表
    {
        throttle_1.1.1.1:[1526868876.497521,152686885.497521...],
        throttle_1.1.1.2:[1526868876.497521,152686885.497521...],
        throttle_1.1.1.3:[1526868876.497521,152686885.497521...],
    } 
 每一個用戶再來訪問時,需先去記錄中剔除過時記錄,再根據列表的長度判斷是否能夠繼續訪問。
 '如何封IP':在防火牆中進行設置
--------------------------------------------------------------------------
# 對註冊用戶,根據用戶名或郵箱進行判斷。
    {
        throttle_xxxx1:[1526868876.497521,152686885.497521...],
        throttle_xxxx2:[1526868876.497521,152686885.497521...],
        throttle_xxxx3:[1526868876.497521,152686885.497521...],
    }
每一個用戶再來訪問時,需先去記錄中剔除過時記錄,再根據列表的長度判斷是否能夠繼續訪問。
\如1分鐘:40次,列表長度限制在40,超過40則不可訪問

Flask框架

Flask框架的優點?

Flask自由、靈活,可擴展性強,透明可控,第三方庫的選擇面廣,
開發時能夠結合最流行最強大的Python庫,

Flask框架依賴組件

# 依賴jinja2模板引擎
# 依賴werkzurg協議

Flask藍圖的做用

# blueprint把實現不一樣功能的module分開.也就是把一個大的App分割成各自實現不一樣功能的module.
# 在一個blueprint中能夠調用另外一個blueprint的視圖函數, 但要加相應的blueprint名.

列舉使用的Flask第三方組件?

# Flask組件
    flask-session  session放在redis
    flask-SQLAlchemy 如django裏的ORM操做
    flask-migrate  數據庫遷移
    flask-script  自定義命令
    blinker  信號-觸發信號
# 第三方組件
    Wtforms 快速建立前端標籤、文本校驗
    dbutile     建立數據庫鏈接池
    gevnet-websocket 實現websocket
# 自定義Flask組件
    自定義auth認證 
    參考flask-login組件

簡述Flask上下文管理流程?

# a、簡單來講,falsk上下文管理能夠分爲三個階段:
  一、'請求進來時':將請求相關的數據放入上下問管理中
  二、'在視圖函數中':要去上下文管理中取值
  三、'請求響應':要將上下文管理中的數據清除
# b、詳細點來講:
  一、'請求剛進來':
        將request,session封裝在RequestContext類中
        app,g封裝在AppContext類中
        並經過LocalStack將requestcontext和appcontext放入Local類中
  二、'視圖函數中':
        經過localproxy--->偏函數--->localstack--->local取值
  三、'請求響應時':
        先執行save.session()再各自執行pop(),將local中的數據清除

Flask中的g的做用?

# g是貫穿於一次請求的全局變量,當請求進來將g和current_app封裝爲一個APPContext類,
# 再經過LocalStack將Appcontext放入Local中,取值時經過偏函數在LocalStack、local中取值;
# 響應時將local中的g數據刪除:

Flask中上下文管理主要涉及到了那些相關的類?並描述類主要做用?

RequestContext  #封裝進來的請求(賦值給ctx)
AppContext      #封裝app_ctx
LocalStack      #將local對象中的數據維護成一個棧(先進後出)
Local           #保存請求上下文對象和app上下文對象

爲何要Flask把Local對象中的的值stack 維護成一個列表?

# 由於經過維護成列表,能夠實現一個棧的數據結構,進棧出棧時只取一個數據,巧妙的簡化了問題。
# 還有,在多app應用時,能夠實現數據隔離;列表裏不會加數據,而是會生成一個新的列表
# local是一個字典,字典裏key(stack)是惟一標識,value是一個列表

Flask中多app應用是怎麼完成?

請求進來時,能夠根據URL的不一樣,交給不一樣的APP處理。藍圖也能夠實現。
    #app1 = Flask('app01')
    #app2 = Flask('app02')
    #@app1.route('/index')
    #@app2.route('/index2')
源碼中在DispatcherMiddleware類裏調用app2.__call__,
  原理其實就是URL分割,而後將請求分發給指定的app。
以後app也按單app的流程走。就是從app.__call__走。

在Flask中實現WebSocket須要什麼組件?

gevent-websocket

wtforms組件的做用?

#快速建立前端標籤、文本校驗;如django的ModelForm

Flask框架默認session處理機制?

解釋Flask框架中的Local對象和threading.local對象的區別?

Flask中 blinker 是什麼?

# flask中的信號blinker
信號主要是讓開發者但是在flask請求過程當中定製一些行爲。
或者說flask在列表裏面預留了幾個空列表,在裏面存東西。
簡言之,信號容許某個'發送者'通知'接收者'有事情發生了
@ before_request有返回值,blinker沒有返回值

# 10個信號

request_started = _signals.signal('request-started') #請求到來前執行

request_finished = _signals.signal('request-finished') #請求結束後執行

before_render_template = _signals.signal('before-render-template')#模板渲染前執行

template_rendered = _signals.signal('template-rendered')#模板渲染後執行

got_request_exception = _signals.signal('got-request-exception') #請求執行出現異常時執行

request_tearing_down = _signals.signal('request-tearing-down')#請求執行完畢後自動執行(不管成功與否)

appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 請求上下文執行完畢後自動執行(不管成功與否)

appcontext_pushed = _signals.signal('appcontext-pushed') #請求app上下文push時執行

appcontext_popped = _signals.signal('appcontext-popped') #請求上下文pop時執行

message_flashed = _signals.signal('message-flashed')#調用flask在其中添加數據時,自動觸發
相關文章
相關標籤/搜索