Flask------一些面試題


1.請手寫一個flask的hello world。


 

hello.py中

#coding = utf-8

# 第一步:導入Flask類
from flask import Flask
app = Flask(__name__)

@app.route("/")
def helloworld():
    return "<h1>hello world</h1>"

if __name__ == " __main__":
    app.run(debug=True)

2.Flask框架的優勢及適用場景?


 

優勢:

1.輕量;(Micro Framework)

2.簡潔

3.擴展性好*

4 第三方庫的選擇面廣,開發時可以結合自己喜歡用的輪子,也可以結合強大的python庫

5.核心(werzeugjinja2),jinja2就是指模板引擎。

應用場景:

  適用於小型網站,適用於開發web服務的API;

  開發大型網站也毫無壓力,但是代碼架構需要開發者自己設計;

Flask和Nosql數據庫的結合優於django

3.Flask框架組件


 

flask_sqlalchemy:將Flask和SQLAlchemy很好的結合在一起,如django中的ORM操作

flask_script:用於生成命令,在項目根目錄路徑下使用命令;例如:python manage.py runserver 

flask_migrate:用來實現數據庫遷移(依賴flask_script)

flask-session:session放在redis里面

blinker:信號-觸發信號

  PS:# flask中的信號blinker 信號主要是讓開發者可是在flask請求過程中定制一些行為。 或者說flask在列表里面預留了幾個空列表,在里面存東西。 簡言之,信號允許某個'發送者'通知'接收者'有事情發生了

4.Flask藍圖的作用


 

# blueprint把實現不同功能的module分開.也就是把一個大的App分割成各自實現不同功能的module.

# 在一個blueprint中可以調用另一個blueprint的視圖函數, 但要加相應的blueprint名.

通常情況下,我是使用flask框架的項目組織結構是這樣的:

我們看看視圖方法:

#views.py
from app import app


@app.route('/user/index')
def index():
    return 'user_index'

@app.route('/user/show')
def show():
    return 'user_show'

@app.route('/user/add')
def add():
    return 'user_add'

@app.route('/admin/index')
def adminindex():
    return 'admin_index'

@app.route('/admin/show')
def adminshow():
    return 'admin_show'

@app.route('/admin/add')
def adminadd():
    return 'admin_add'

#從視圖方法中,我們看到有6個視圖,分別對應admin,user兩個不同用戶的3個功能index,add,show.
這樣寫顯然沒問題,但是明顯與python提倡的模塊化沖突;

當然根據Pythonic特點,我們肯定希望盡可能的把代碼盡量的模塊化,讓我們的代碼看起來更加的優雅和順暢,這個時候flask.Blueprint(藍圖)就派上用場了

一個藍圖定義了可用於單個應用的視圖,模板,靜態文件等等的集合

上面的例子中只有兩個組件(模塊)admin,user,我們可以創建名為admin.py和user.py的兩個文件,分別在里面創建兩個藍圖的實例對象admin,user.

#admin.py
from flask import Blueprint,render_template, request

admin = Blueprint('admin',__name__)

@admin.route('/index')
def index():
    return render_template('admin/index.html')

@admin.route('/add')
def add():
    return 'admin_add'

@admin.route('/show')
def show():
    return 'admin_show'

#要想創建一個藍圖對象,你需要import flask.Blueprint()類並用參數name和import_name初始化。import_name通常用__name__,一個表示當前模塊的特殊的Python變量,作為import_name的取值。
 
         
#user.py

from
flask import Blueprint, render_template, redirect user = Blueprint('user',__name__) @user.route('/index') def index(): return render_template('user/index.html') @user.route('/add') def add(): return 'user_add' @user.route('/show') def show(): return 'user_show'

視圖函數已經分開了 再看看view.py

#view.py

from app import app
from .admin import admin
from .user import user
#這里分別給app注冊了兩個藍圖admin,user
#參數url_prefix='/xxx'的意思是設置request.url中的url前綴,
#即當request.url是以/admin或者/user的情況下才會通過注冊的藍圖的視圖方法處理請求並返回
app.register_blueprint(admin,url_prefix='/admin')
app.register_blueprint(user, url_prefix='/user')

再看看使用藍圖后的項目結構:

如果項目不大的話就沒有必要使用藍圖了,我們甚至可以把除了所有css,js,html的代碼都寫到一個文件中去。

5.列舉Flask使用的第三方組件


 

# 第三方組件:

  Wtforms:快速創建前端標簽、文本校驗

  dbutile:創建數據庫連接池

  gevent-websocket:實現websocket

# 自定義Flask組件

  auth認證

  參考flask-login

6.簡述Flask上下文管理流程。


 

Flask中有兩種上下文,請求上下文應用上下文

request和session都屬於請求上下文對象。

  request:封裝了HTTP請求的內容,針對的是http請求。舉例:user = request.args.get('user'),獲取的是get請求的參數。

  session:用來記錄請求會話中的信息,針對的是用戶信息。舉例:session['name'] = user.id,可以記錄用戶信息。還可以通過session.get('name')獲取用戶信息

current_app和g都屬於應用上下文對象。

  current_app:表示當前運行程序文件的程序實例。

  g:處理請求時,用於臨時存儲的對象,每次請求都會重設這個變量。比如:我們可以獲取一些臨時請求的用戶信息。

  當調用app = Flask(_name_)的時候,創建了程序應用對象app;
  request 在每次http請求發生時,WSGI server調用Flask.call();然后在Flask內部創建的request對象;
  app的生命周期大於request和g,一個app存活期間,可能發生多次http請求,所以就會有多個request和g。
  最終傳入視圖函數,通過return、redirect或render_template生成response對象,返回給客戶端。
他們的區別:

 請求上下文:保存了客戶端和服務器交互的數據。 應用上下文:在flask程序運行過程中,保存的一些配置信息,比如程序文件名、數據庫的連接、用戶信息等

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

7.Flask中g的作用


 

g:gloal

1.g對象是專門用來來保存用戶數據的;

2.g對象在一次請求中的所有的代碼的地方,都是可以使用的

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

8.如何編寫flask的離線腳本


 

 

9.Flask中上下文管理主要是涉及到了哪些相關的類?並描述類主要的作用


 

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

10.為什么要Flask把Local對象中的值stack維護程一個列表


 

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

11.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__走。

12.在Flask中實現WebSocket需要什么組件?


 

gevent-websocet

13.wtforms組件的作用?


 

定義:WTForms是一個支持多個web框架的form組件,主要用於對用戶請求數據進行驗證。

兩種導入方式:

from wtforms import Form
from flask_wtf  import FlaskForm  需要設置csrf

安裝:

pip3 install wtforms

作用:

  快速創建前端標簽、文本校驗:如django的ModelForm

14.Flask框架默認的session處理機制?


 

15.解釋Flask框架中Local對象和threadinglocal對象的區別?


 

# a.threading.local
作用:為每個線程開辟一塊空間進行數據存儲(數據隔離)。

問題:自己通過字典創建一個類似於threading.local的東西。
storage = {
   4740: {val: 0},
   4732: {val: 1},
   4731: {val: 3},
   }

# b.自定義Local對象
作用:為每個線程(協程)開辟一塊空間進行數據存儲(數據隔離)。

class Local(object):
   def __init__(self):
      object.__setattr__(self, 'storage', {})
   def __setattr__(self, k, v):
      ident = get_ident()
      if ident in self.storage:
         self.storage[ident][k] = v
      else:
         self.storage[ident] = {k: v}
   def __getattr__(self, k):
      ident = get_ident()
      return self.storage[ident][k]
obj = Local()
def task(arg):
   obj.val = arg
   obj.xxx = arg
   print(obj.val)
for i in range(10):
   t = Thread(target=task, args=(i,))
   t.start()

16.SQLAlchemy中的session和scoped_session的區別?


 

# Session:
  由於無法提供線程共享功能,開發時要給每個線程都創建自己的session
  打印sesion可知他是sqlalchemy.orm.session.Session的對象
# scoped_session:
  為每個線程都創建一個session,實現支持線程安全
  在整個程序運行的過程當中,只存在唯一的一個session對象。
  創建方式:通過本地線程Threading.Local()
  # session=scoped_session(Session)
  創建唯一標識的方法(參考flask請求源碼)

17.SQLAlchemy如何執行原生SQL?


 

# 使用execute方法直接操作SQL語句(導入create_engin、sessionmaker)
  engine=create_engine('mysql://root:pwd@127.0.0.1/database?charset=utf8')
  DB_Session = sessionmaker(bind=engine)
  session = DB_Session()
  session.execute('select * from table...;')

18.ORM的實現原理?


 

# ORM的實現基於以下三點

  映射類:描述數據庫表結構,

  映射文件:指定數據庫表和映射類之間的關系

  數據庫配置文件:指定與數據庫連接時需要的連接信息(數據庫、登錄用戶名、密碼or連接字符串)

19.DBUtils模塊的作用?


 

# DBUtils是數據庫連接池模塊

使用模式:

  1、為每個線程創建一個連接,連接不可控,需要控制線程數

  2創建指定數量的連接在連接池,當線程訪問的時候去取,不夠了線程排隊,直到有人釋放*

兩種寫法:

  1.用靜態方法裝飾器,通過直接執行類的方法來連接使用數據庫;

  2.通過實例化對象,通過對象調用方法使用語句;

20.SQLAlchemy中的如何為表設置引擎和字符編碼?


 

sqlalchemy設置編碼字符集,一定要在數據庫訪問的URL上增加'charset=utf8',否則數據庫的連接就不是'utf8'的編碼格式

1. 設置引擎編碼方式為utf8:

  engine = create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True) 

2. 設置數據庫表編碼方式為utf8:

  engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/sqldb01?charset=utf8")  

class UserType(Base):
  __tablename__ = 'usertype' i
  d = Column(Integer, primary_key=True)
  caption = Column(String(50), default='管理員')
   # 添加配置設置編碼
  __table_args__ = {
     'mysql_charset':'utf8'
  }

這樣生成的SQL語句就自動設置數據表編碼為utf8了,__table_args__還可設置存儲引擎、外鍵約束等等信息。

21.SQLAlchemy中如何設置聯合唯一索引

通過'UniqueConstraint'字段來設置聯合唯一索引

__table_args=(UniqueConstraint('h_id','username',name='_h_username_uc'))

#h_id和username組成聯合唯一約束

 持續更新....


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM