Fork me on GitHub

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组成联合唯一约束

 持续更新....

posted @ 2019-05-11 20:10  Utopia-Clint  阅读(1467)  评论(0编辑  收藏  举报