面试
1.数据库的三大范式
| 1.数据库的三大范式 |
| 第一范式(1NF)是指数据库表的每一列都是不可分割 |
| |
| 第二范式(2NF):如果表是单主键,那么主键以外的列必须完全依赖于主键:如果表是复合主键,那么主键以外的列必须完全依赖于主键,不能仅依赖主键的一部分。 |
| |
| 第三范式(3NF)要求: 表中的非主键列必须和主键直接相关而不能间接相关: 也就是说: 非主键列之间不能相关依赖 不存在传递依赖 |
2 mysql有哪些索引类型,分别有什么作用
| 聚簇索引,聚集索引,主键索引,主键,如果不存在主键,隐藏一个主键,构造聚簇索引 |
| 辅助索引, 普通索引 index |
| 唯一索引 unique |
| 联合索引,组合索引,多列索引: unique_together |
3. 事务的特性和隔离级别
| 事务的四大特性: |
| 原子性: |
| |
| 隔离性: |
| |
| 一致性: |
| |
| 持久性: |
| |
| |
| 隔离级别: |
| |
| |
| |
| |
上节课回顾
| |
| -django 大而全 |
| -flask 小而精 |
| -sanic |
| -fastapi |
| -同步框架和异步框架 |
| |
| |
| |
| -wsgiref |
| -werkzeug |
| |
| |
| |
| |
| |
| |
| 1 注册路由 app.route(路径,methods=[请求方式get, post]) |
| 2 新手四件套: |
| -render_template 渲染模板 跟 django有区别 |
| -redirect 重定向 |
| -return 字符串 返回字符串 |
| -jsonify 返回json格式 |
| |
| 3 请求的request对象,是全局的,直接导入使用即可,在不同试图函数中不会混乱 |
| request.method 请求方式 |
| request.form post请求的body体的内容转成了字典 |
| |
| 4 session 全局的,直接导入使用即可,一定要指定密钥 |
| app.secret_key = 'asdasdnushdqio' |
| 放值: session['name'] = 'lqz' |
| 取值: session.get('name') |
| |
| 5 模板的渲染 |
| -兼容django的dtl |
| -更强大,客户加括号,字典可以.get .values().items() |
| -{% for %} |
| |
| 6 转换器@app.route('/detail<int:pk>') |
| |
| |
| |
| -app.config 对象 |
| -配置中心 |
| |
| |
| app.add_url_rule 方法 |
| 参数: |
| rule,URL 规则 |
| view_func, 视图函数名称 |
| defaults = None, 默认值,当URL中无参数,函数需要参数时,使用defaults = {'k':'v'} |
| 为函数提供参数 |
| endpoint = None, 名称,用户反向生成URL,即:url_for('名称') |
| methods = None, 允许的请求方式, 如: ["GET","POST"] |
今日内容
1 cbv分析
| |
| |
| from flask import Flask,request |
| from flask.views import View, MethodView |
| |
| app = Flask(__name__) |
| |
| app.debug = True |
| |
| |
| class IndexView(MethodView): |
| def get(self): |
| print(request.method) |
| return 'get 请求' |
| |
| def post(self): |
| print(request.method) |
| return |
| |
| app.add_url_rule('/index', endpoint='index', view_func=IndexView.as_view('index')) |
| if __name__ == '__main__': |
| app.run() |
1.1 源码分析
| |
| def as_view(cls, name, *class_args, **class_kwargs): |
| def view(**kwargs: t.Any) -> ft.ResponseReturnValue: |
| |
| return current_app.ensure_sync(self.dispatch_request)(**kwargs) |
| return view |
| |
| |
| |
| def dispatch_request(self, **kwargs): |
| |
| meth = getattr(self, request.method.lower(), None) |
| |
| return current_app.ensure_sync(meth)(**kwargs) |
| |
| |
| |
| |
| |
| |
| -@app.route('/index')---> 没有传endpoint |
| -endpoint 就是None---> 调用了app.add_url_rule,传入了None |
| if endpoint is None: |
| endpoint = _endpoint_from_view_func(view_func) |
| -_endpoint_from_view_func 就是返回函数的名字 |
| |
| |
| |
| view.__name__ = name |
| |
| 简写成:app.add_url_rule('/index',view_func=view) |
| |
| |
| |
| -放在路由下面 |
| -路由必须传endpoint, 如果不传,又报错 |
| |
| |
| |
| def dispatch_request(self) -> ft.ResponseReturnValue: |
| raise NotImplementedError() |
| |
| |
| |
| decorators = [auth,] |
| |
| if cls.decorators: |
| for decorator in cls.decorators: |
| view = decorator(view) |
| |
| |
| -1 as_view 执行流程跟django一样 |
| -2 路径如果不传别名,别名就是函数名(endpoint) |
| -3 视图函数加多个装饰器(上下顺序和必须传endpoint) |
| -4 视图类必须继承MethodView, 否则需要重写 dispatch_request |
| -5 视图类加装饰器: 类属性decorators = [auth,] |
2 模板
2.1 py
| from flask import Flask, render_template,Markup |
| |
| app = Flask(__name__, template_folder='templates', static_folder='static') |
| app.debug=True |
| |
| |
| def add(a,b): |
| return a+b |
| @app.route('/') |
| def index(): |
| a='<a href="http://www.baidu.com">点我看美女</a>' |
| a=Markup(a) |
| return render_template('index.html',name='lqz',a=a,add=add) |
| |
| |
| if __name__ == '__main__': |
| app.run() |
| |
2.2 html
| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>Title</title> |
| </head> |
| <body> |
| <h1>模板语法,static</h1> |
| <img src="/static/1.jpg" alt=""> |
| |
| <h1>模板语法,if</h1> |
| {% if name %} |
| <h1>Hello {{ name }}!</h1> |
| {% else %} |
| <h1>Hello World!</h1> |
| {% endif %} |
| |
| <h1>模板语法,标签渲染</h1> |
| {{a|safe}} |
| {{a}} |
| |
| <h1>模板语法,执行函数</h1> |
| {{add(4,5)}} |
| |
| </body> |
| </html> |
3 请求与响应
| from flask import Flask, request, |
| make_response, render_template |
| |
| app = Flask(__name__) |
| app.debug = True |
| |
| |
| @app.route('/', methods=['GET', 'POST']) |
| def index(): |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| print(request.method) |
| print(request.args) |
| print(request.form) |
| print(request.values) |
| print(request.cookies) |
| print(request.headers) |
| print(request.path) |
| print(request.full_path) |
| print(request.url) |
| print(request.base_url) |
| print(request.host_url) |
| print(request.host) |
| |
| obj = request.files['file'] |
| obj.save(obj.filename) |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| response = render_template('index.html') |
| res = make_response(response) |
| print(type(res)) |
| res.headers['yy']='yy' |
| return res |
| |
| |
| if __name__ == '__main__': |
| app.run() |
4 session及源码分析
4.1 session的使用
| from flask import Flask,request,session,render_template,redirect |
| |
| app = Flask(__name__) |
| app.debug = True |
| app.secret_key = 'asdfas33asdfasf' |
| |
| @app.route('/login', methods=['GET', 'POST']) |
| def login(): |
| if request.method == 'GET': |
| return render_template('login.html') |
| else: |
| name = request.form.get('name') |
| password = request.form.get('password') |
| print(password) |
4.2 源码的分析
| |
| |
| |
| |
| -加密后,放到了cookie中,如果session发生了变化,我们的cookie也会跟着变 |
| |
| |
| |
| |
| |
| |
| def open_session(self, app, request) : |
| |
| val = request.cookies.get(self.get_cookie_name(app)) |
| |
| if not val: |
| return self.session_class() |
| max_age = int(app.permanent_session_lifetime.total_seconds()) |
| try: |
| |
| data = s.loads(val, max_age=max_age) |
| return self.session_class(data) |
| except BadSignature: |
| |
| return self.session_class() |
| |
| |
| |
| |
| def save_session(self, app, session, response) : |
| name = self.get_cookie_name(app) |
| |
| expires = self.get_expiration_time(app, session) |
| val = self.get_signing_serializer(app).dumps(dict(session)) |
| response.set_cookie( |
| name, |
| val, |
| expires=expires, |
| ) |
| |
| |
| |
| |
| |
| 只需要写个类,重写open_session,save_session自己写 |
5 闪现
| |
| - 档次请求先把一些数据 放在某个位置 |
| - 下一次请求,把这些数据取出来,取完,就没了 |
| |
| |
| 1 可以跨请求,来保存数据 |
| 2 当次请求,访问出错,被重定向到其他地址,重定向到这个地址后,拿到当时的错误 |
| |
| |
| -msssage 框架 |
| |
| |
| -设置 闪现 |
| -flash('%s,我错了'%name) ,可以设置多次,放到列表中 |
| flash('超时错误',category="debug") 分类存 |
| -获取 闪现 |
| -get_flashed_messages() ,取完就删除 |
| -get_flashed_messages(category_filter=['debug'])分类取 |
| |
| |
| |
6 请求扩展
| |
| |
| |
| |
| -before_request: 请求来了会走,如果他发挥了四件套,就结束了 |
| -after_request: 请求走了会触发,一定要返回response对象 |
| -before_first_request:第一次来了会走 |
| -teardown_request:无论是否出异常,会走 |
| -errorhandler:监听状态码,404 500 |
| -template_global:标签 |
| -template_filter:过滤器 |
| from flask import Flask, request,render_template |
| |
| app = Flask(__name__) |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| @app.template_global() |
| def add(a1, a2): |
| return a1 + a2 |
| |
| |
| @app.template_filter() |
| def db(a1, a2, a3): |
| return a1 + a2 + a3 |
| |
| |
| @app.route('/') |
| def index(): |
| |
| |
| return render_template('index1.html') |
| |
| |
| if __name__ == '__main__': |
| app.run() |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构