Skip to main content

Python-Flask 面试

Flask 面试

1. 描述 Flask 框架及其主要用途

  • 使用 Python 编写的轻量级 Web 应用框架,适用于小型项目、原型设计,以及作为学习 web 开发的工具。
  • Flask 的主要特性包括, WSGI (Web Server Gateway Interface) 兼容, 路由, 模版渲染(Jinja2), 调试支持, 开发服务器, 单元测试支持, 可扩展。
  • Flask 以其最小主义的核心理念脱颖而出,即使在扩展功能的同时,它也鼓励开发者按照自己的方式来扩展应用。这种微框架的方式为开发者提供了很多灵活性,允许他们使用最适合他们需求的组件来构建应用。

2. Flask 和 Django 在 Web 开发中有什么不同?

  • 设计哲学:
    • Flask: 它是一个微框架,提供了完成 Web 应用开发的最基本工具和功能,如路由、请求响应处理和模板渲染。Flask 的核心简单,它不包括内置的 ORM(对象关系映射)或表单验证工具。
    • Django: 它是一个全栈框架,遵循“电池包括在内”的哲学,这意味着它包括了创建一个功能完备 Web 应用所需要的几乎所有东西,例如一个内置的 ORM 系统、一个内置的管理界面、表单序列化与验证工具、文件上传支持、用户认证系统等。
  • 开箱即用的功能:
    • Flask: Flask 核心非常轻量,Flask 通常需要通过 Flask 扩展来添加这些额外的功能。
    • Django: Django 提供了丰富的功能集,包括自动的管理界面、数据库迁移工具、内置的类视图用于快速开发、中间件支持等。
  • 灵活性与控制:
    • Flask: 更加灵活
    • Django: 约定俗成,默认解决方案
  • 适用案例
    • Flask: 通常用于小到中等规模的项目,API 开发,微服务架构,以及当开发者希望手动选择组件的项目。
    • Django: 适合快速开发大型项目,内容管理系统(CMS),有复杂数据库模型和需要高级功能(如用户验证、内容管理等)的应用。

3. 解释在 Flask 中如何处理路由。

  • 使用 @app.route("/") 装饰器来告诉 Flask URL "/" 匹配哪个函数
  • 加入可变路径, 使用 <> 表示
  • 加入方法,使用 keyword parameters, 即 methods=["GET", "POST"]

4. 在 Flask 应用中如何管理用户会话?

  • 在 Flask 应用中管理用户会话,可以使用 Flask 自带的 session 对象。这个对象背后是一个基于密钥的签名的 cookie ,它可以存储在用户浏览器中。
  • 如果你需要存储大量数据,session 也可以将数据存储到 redis/数据库 中,通过在初始化时提供 redis/数据库 的连接设置
  • session["user_id"] = user_id
  • session["authenicated"] = True

5. 如何在 Flask 应用中实现数据库集成的?

(psycopg2) ORM: Flask-SQLAlchemy

pip install Flask-SQLAlchemy

Define table

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)

def __repr__(self):
return '<User %r>' % self.username
db.create()
# db.create_all()

db.session.add(new_user)
db.session.commit()

User.query.all()
User.query.filter_by(username="xxx").first()
User.query.filter_by(username="xxx").order_by(model.Entry.amount.desc())
User.get([pk])

select(user_table).where(user_table.c.name == "spongebob")

db.session.delete(user)
db.session.commit()

6. 解释 Flask 中的请求和响应对象

在 Flask 中,请求和响应对象是处理 HTTP 请求和生成 HTTP 响应的核心部分。Flask 使用 Werkzeug 库来提供请求和响应对象,并且使它们易于使用和扩展。

flask.Request

  • 请求方法: 可以通过 request.method 访问请求的方法,例如 GET, POST, PUT, DELETE 等。
  • URL: request.path 返回请求的路径,而 request.url 返回包括查询字符串在内的完整 URL。
  • 表单数据: 对于 POST 或 PUT 请求,表单数据可以通过 request.form 来访问。
  • 查询字符串: 查询字符串可以通过 request.args 来访问。
  • JSON 数据: 如果请求是一个 JSON 请求,那么可以通过 request.json 来访问 JSON 数据。
  • 文件: 上传的文件可以通过 request.files 来访问。
  • Cookies: 可以通过 request.cookies 来读取请求中发送的 cookies。
  • Headers: 请求头可以通过 request.headers 来访问。
  • query_string

flask.Response 响应对象代表服务器返回给客户端的 HTTP 响应。它包括状态码、响应头、响应体等信息。

  • 字符串: Flask 会将字符串包装成一个带有 200 OK 状态码和 text/htmlMIME 类型的响应对象。
  • 响应对象: 如果你创建了一个 Response 对象,可以直接返回它。这在需要更复杂的响应(如不同的 MIME 类型或特殊的头部信息)时非常有用。
  • 元组: 你可以返回一个包含响应体、状态码和头部信息的元组。例如:return 'Hello World!', 200, {'Content-Type': 'text/plain'}。

7. 在 Flask 中如何实现 RESTful API?

  • Create Flask app
  • Use Flask-restful to createa a API app
from flask_restful import Api
api = Api(app)
  • Define resource class
from flask_restful import Resource
class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}
  • Add resource to api
api.add_resource(HelloWorld, '/')
  • Start api server
if __name__ == '__main__':
app.run(debug=True)

8. Flask 的蓝图(Blueprints)是什么,以及为什么要使用它们?

在 Flask 中,蓝图(Blueprints)是一种组织和重用代码的方式,类似于 Django 中的应用。

蓝图允许你将应用分割成不同的组件,每个组件都有自己的视图函数、模板、静态文件等。这种划分可以帮助你构建大型的、模块化的应用,并且保持代码的清晰和可维护性。

它能够帮助我们把最相关的代码模块化,并且模块与模块之间是相互调用。对于可能出现重复的路由,我们可以注册的过程中提供 prefix_url 的方式为每个模块提供独特的 url 地址。

这能帮助我们简化大型应用代码的管理成本。

9. 描述在 Flask 应用中实现安全措施的策略。

在 Flask 应用中实现安全措施是至关重要的,以保护应用避免各种网络攻击和漏洞利用。

  1. Protocal
    1. 使用 HTTPS
    2. Use secure HTTP head
      • header such as X-Content-Type-Options, X-Frame-Options
      • Use Flask-Taliman for settings
  2. Validate all inputs
    1. 防止跨站脚本攻击 (XSS)
      • escape all values
      • Use {{ variable | safe }} filter to render html
    2. 防止跨站请求伪造 (CSRF, Cross-Site Request Forgery):
      • Use Flask-WTF or Flask-SeaSurf
      • Ensure all form submit contains CSRF token
    3. 密码处理:
      • No save string directly for password
      • Use strong password then weak password
      • Hash password with bcrypt package
    4. Limit uploaded file type and size
  3. Database
    • SQL 注入保护: 使用 ORM 像 SQLAlchemy 这样的库来避免拼接 SQL 查询。
  4. Codebasde
    • Handle all error and exception in app creat custome error page
    • limit log content to filter pasword of personal information
    • Use pylint tool to check the syntax of codes
  5. Outside
    • AWS WAF & Shield (Detect bot traffic, DDoS: Distributed denial-of-service)
    • Rate Limiting
      • application
        • Flask-Limiter
      • Infrastructure
        • AWS WAF(Web Application Firewall)
        • API Gateway
        • Apploication Load Blancer(ALB)
      • Cache
        • Redis
        • AWS ElasticCache

10. 如何使用 Flask-Migration

install

pip install Flask-Migration

setup app and create model

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///yourdatabase.db'

db = SQLAlchemy(app)
migrate = Migrate(app, db)

# Define your models (example)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)

# Other models can follow...

initialze database

db.create_all()

create and apply migrations

flask db migrate -m "Initial migration."
flask db upgrade
flask db downgrade

migrations_file.py

"""Create account table

Revision ID: 011ae1053cfe
Revises: None
Create Date: 2021-01-01 12:34:56.789012

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic
revision = '011ae1053cfe'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
# Instructions for upgrading the database to the next revision:
op.create_table(
'account',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('name', sa.String(50), nullable=False),
sa.Column('description', sa.Unicode(200)),
)

def downgrade():
# Instructions for downgrading the database to the previous revision:
op.drop_table('account')