Flask框架学习笔记

Flask框架学习笔记

简介和安装

Flask是一个基于Python的轻量级Web应用框架,它简洁、易用,成为了许多开发人员的首选Python Web框架。

核心特点

  1. 轻量级: Flask是一个轻量级框架,核心功能相对较小,但通过扩展可以实现丰富的功能。
  2. 灵活: Flask提供了大量灵活性,开发人员可以选择适合其项目需求的工具和库。
  3. 易学易懂: 基于Python开发,使用了简洁的代码结构,使其容易学习和使用。

可以使用pip来安装Flask,运行以下命令:

pip install Flask

安装后,可以通过Pycharm创建一个Flask项目,项目结构如下

demo1/
    static/
    templates/
    app.py

路由和视图函数

路由用于将URL映射到相应的视图函数,视图函数则负责处理请求并返回相应的内容。

请求

demo1/app.py

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'Hello 中国!'


@app.route("/profile")
def profile():
    return "我是个人中心!"


@app.route("/blog/list")
def blog_list():
    return "我是博客列表!"

# 传参方式一:将参数固定到了path中(GET)
@app.route("/blog/<int:blog_id>")
def blog_detail(blog_id):
    return "您访问的博客是:%s" % blog_id


# 传参方式二:查询字符串的方式传参(GET)
# /book/list:会给我返回第一页的数据
# /book/list?page=2:获取第二页的数据
@app.route('/book/list')
def book_list():
    # arguments:参数
    # request.args:类字典类型
    page = request.args.get("page", default=1, type=int)
    return f"您获取的是第{page}的图书列表!"

# 传参方式三:表单传参(POST)
@bp.route("/qa/publish", methods=['POST'])
def publish_question():
    form = QuestionForm(request.form)
    title = form.title.data
    content = form.content.data
    print(title)
    print(content)

# 1. debug模式:
# 1.1. 开启debug模式后,只要修改代码后保存,就会自动重新加载,不需要手动重启项目
# 1.2. 如果开发的时候,出现bug,如果开启了debug模式,在浏览器上就可以看到出错信息

# 2. 修改host:
# 主要的作用:就是让其他电脑能访问到我电脑上的flask项目

# 3. 修改port端口号:
# 主要的作用:如果5000端口被其他程序占用了,那么可以通过修改port来监听的端口号


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

响应

可以响应纯文本,HTML、JSON、文件,重定向

from flask import Flask,render_template,redirect,jsonify,send_file  
@app.route('/')  
def index():
    return "hello world"

@app.route("/login")
def login():
    return render_template('login.html')

@app.route('/hi')
def hi():
    return redirect('/')
    
@app.route("/hello")
def hello():
    return jsonify({"name":"xiaoming","age":16})
    
@app.route("/web")
def web():
    return send_file("./small.png")

Jinja2模板系统

demo2/app.py

from flask import Flask, render_template
from datetime import datetime

app = Flask(__name__)


def datetime_format(value, format="%Y年%m月%d日 %H:%M"):
    return value.strftime(format)


app.add_template_filter(datetime_format, "dformat")


class User:
    def __init__(self, username, email):
        self.username = username
        self.email = email


@app.route('/')
def hello_world():
    user = User(username="张三", email="xx@qq.com")
    person = {
        "username": "李四",
        "email": "lisi@qq.com"
    }
    return render_template("index.html", user=user, person=person)


@app.route("/blog/<blog_id>")
def blog_detail(blog_id):
    return render_template("blog_detail.html", blog_id=blog_id, username="王五")


@app.route("/filter")
def filter_demo():
    user = User(username="赵六xxxx", email="xx@qq.com")
    mytime = datetime.now()
    return render_template("filter.html", user=user, mytime=mytime)


@app.route("/control")
def control_statement():
    age = 18
    books = [{
        "name": "三国演义",
        "author": "罗贯中"
    }, {
        "name": "水浒传",
        "author": "施耐庵"
    }, ]
    return render_template("control.html", age=age, books=books)


@app.route("/child1")
def child1():
    return render_template("child1.html")


@app.route("/child2")
def child2():
    return render_template("child2.html")


@app.route('/static')
def static_demo():
    return render_template("static.html")


if __name__ == '__main__':
    app.run()

给模板传入一般数据

demo2/templates/blog_detail.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>博客详情</title>
</head>
<body>
  <p>您的用户名是:{{ username }}</p>
  <h1>您访问的博客详情是:{{ blog_id }}</h1>
</body>
</html>

给模板传入对象和字典

demo2/templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>首页</title>
</head>
<body>
<h1>首页</h1>
<div>{{ user.username }} / {{ user.email }}</div>
<div>{{ person['username'] }} / {{ person.username }}</div>
</body>
</html>

demo2/templates/filter.html: 自定义过滤器

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>过滤器使用demo</title>
</head>
<body>
<div>{{ user.username }}-{{ user.username|length }}</div>
<div>{{ mytime|dformat }}</div>
</body>
</html>

模板内的流程控制

demo2/templates/control.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>控制语句Demo</title>
</head>
<body>
{% if age>18 %}
  <div>您已经满18岁,可以进入网吧!</div>
{% elif age==18 %}
  <div>您刚满18岁,需要父母陪同才能进入!</div>
{% else %}
  <div>您未满18岁,不能进入网吧!</div>
{% endif %}


{% for book in books %}
  <div>图书名称:{{ book.name }},图书作者:{{ book.author }}</div>
{% endfor %}
</body>
</html>

模板的继承

demo2/templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>{% block title %}{% endblock %}</title>
</head>
<body>
<ul>
  <li><a href="#">首页</a></li>
  <li><a href="#">新闻</a></li>
</ul>
{% block body %}
{% endblock %}
<footer>这是底部的标签</footer>
</body>
</html>

demo2/templates/child1.html

{% extends "base.html" %}

{% block title %}
我是子模板的标题
{% endblock %}

{% block body %}
我是子模板的body
{% endblock %}

demo2/templates/child2.html

{% extends "base.html" %}

{% block title %}
我是child2
{% endblock %}

{% block body %}
我是child2
{% endblock %}

模板中引用静态文件

demo2/templates/static.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
  <script src="{{ url_for('static', filename='js/my.js') }}"></script>
</head>
<body>
<img src="{{ url_for('static', filename='images/ironman.jpg') }}" alt="">
</body>
</html>

SQLAlchemy ORM

ORM模型映射成表的三步

  • flask db init:这步只需要执行一次
  • flask db migrate:识别ORM模型的改变,生成迁移脚本
  • flask db upgrade:运行迁移脚本,同步到数据库中

用MySQL数据库进行CURD

demo3/app.py

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

app = Flask(__name__)

# 在app.config中设置好连接数据库的信息,然后使用SQLAlchemy(app)创建一个db对象
# SQLAlchemy会自动读取app.config中连接数据库的信息
HOSTNAME = "127.0.0.1"
PORT = 3306
USERNAME = "root"
PASSWORD = "123456"
DATABASE = "database_learn"
app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
db = SQLAlchemy(app)

migrate = Migrate(app, db)

# 直接执行SQL语句
# with app.app_context():
#     with db.engine.connect() as conn:
#         rs = conn.execute(text("select 1"))
#         print(rs.fetchone())  # (1,)

class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(100), nullable=False)
    password = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(100))
    signature = db.Column(db.String(100))


# user = User(username="法外狂徒张三", password='111111')
# sql: insert user(username, password) values('法外狂徒张三', '111111');

class Article(db.Model):
    __tablename__ = "article"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(200), nullable=False)
    content = db.Column(db.Text, nullable=False)

    # 添加作者的外键
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    # backref:会自动的给User模型添加一个articles的属性,用来获取文章列表
    author = db.relationship("User", backref="articles")

# 将模型同步为数据库中的表,但再修改模型后不能同步修改表
# with app.app_context():
#     db.create_all()

@app.route('/')
def hello_world():
    return 'Hello World!'


@app.route("/user/add")
def add_user():
    # 1. 创建ORM对象
    user = User(username="法外狂徒张三", password='111111')
    # 2. 将ORM对象添加到db.session中
    db.session.add(user)
    # 3. 将db.session中的改变同步到数据库中
    db.session.commit()
    return "用户创建成功!"


@app.route("/user/query")
def query_user():
    # 1. get查找:根据主键查找
    # user = User.query.get(1)
    # print(f"{user.id}: {user.username}-{user.password}")
    # 2. filter_by查找
    # Query:类数组
    users = User.query.filter_by(username="法外狂徒张三")
    for user in users:
        print(user.username)
    return "数据查找成功!"


@app.route("/user/update")
def update_user():
    user = User.query.filter_by(username="法外狂徒张三").first()
    user.password = "222222"
    db.session.commit()
    return "数据修改成功!"


@app.route('/user/delete')
def delete_user():
    # 1. 查找
    user = User.query.get(1)
    # 2. 从db.session中删除
    db.session.delete(user)
    # 3. 将db.session中的修改,同步到数据库中
    db.session.commit()
    return "数据删除成功!"


@app.route("/article/add")
def article_add():
    article1 = Article(title="Flask学习大纲", content="Flaskxxxx")
    article1.author = User.query.get(2)

    article2 = Article(title="Django学习大纲", content="Django最全学习大纲")
    article2.author = User.query.get(2)

    # 添加到session中
    db.session.add_all([article1, article2])
    # 同步session中的数据到数据库中
    db.session.commit()
    return "文章添加成功!"


@app.route("/article/query")
def query_article():
    user = User.query.get(2)
    for article in user.articles:
        print(article.title)
    return "文章查找成功!"


if __name__ == '__main__':
    app.run()

用sqlite做实验

demo3/test1.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

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

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

with app.app_context():
    db.create_all()

RESTFul API

一个简单的基于RESTful风格的API示例,演示了如何使用HTTP动词对资源进行操作。

假设我们有一个用于管理书籍的API。我们可以有以下端点:

创建新书籍

  • 请求方式: POST
  • URL: /api/books
  • 请求体:
{ "title": "The Catcher in the Rye", "author": "J.D. Salinger" }
  • 示例响应:
{ "id": 3, "title": "The Catcher in the Rye", "author": "J.D. Salinger" }

更新特定书籍

  • 请求方式: PUT/PATCH
  • URL: /api/books/{id}
  • 请求体:
{ "title": "New Title" }
  • 示例响应:
{ "id": 3, "title": "New Title", "author": "J.D. Salinger" }

获取所有书籍

  • 请求方式: GET
  • URL: /api/books
  • 示例响应:
[
 { "id": 1, "title": "1984", "author": "George Orwell" },
 { "id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee" }
]

获取特定书籍

  • 请求方式: GET
  • URL: /api/books/{id}
  • 示例响应:
{ "id": 1, "title": "1984", "author": "George Orwell" }

删除特定书籍

  • 请求方式: DELETE
  • URL: /api/books/{id}
  • 示例响应: 204 No Content

这些示例演示了如何使用RESTful风格设计简单的API。在实际开发中,需要考虑更多的安全性、身份验证、错误处理等方面。

问答平台项目

项目配置文件

demo4/config.py

SECRET_KEY = "asdfasdfjasdfjasd;lf"  # 用于加密session

# 数据库配置
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'database_learn'
USERNAME = 'root'
PASSWORD = '123456'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
SQLALCHEMY_DATABASE_URI = DB_URI

# 邮箱配置
MAIL_SERVER = "smtp.qq.com"
MAIL_USE_SSL = True
MAIL_PORT = 465
MAIL_USERNAME = "yourqq@qq.com"
MAIL_PASSWORD = "zyvhrkyjcbzzbifg"
MAIL_DEFAULT_SENDER = "yourqq@qq.com"

解决循环引用问题

demo4/exts.py

from flask_sqlalchemy import SQLAlchemy
from flask_mail import Mail

db = SQLAlchemy()
mail = Mail()

项目入口

demo4/app.py

from flask import Flask, session, g
import config
from exts import db, mail
from models import UserModel
from blueprints.qa import bp as qa_bp
from blueprints.auth import bp as auth_bp
from flask_migrate import Migrate

app = Flask(__name__)

# 配置
app.config.from_object(config)
db.init_app(app)
mail.init_app(app)

# 迁移
migrate = Migrate(app, db)

# 注册蓝图 (blueprint:用来做块化模的)
app.register_blueprint(qa_bp)
app.register_blueprint(auth_bp)


# 钩子函数
# before_request/ before_first_request/ after_request
@app.before_request
def my_before_request():
    user_id = session.get("user_id")
    if user_id:
        user = UserModel.query.get(user_id)
        setattr(g, "user", user)
    else:
        setattr(g, "user", None)


@app.context_processor
def my_context_processor():
    return {"user": g.user}


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

登录保护装饰器

demo4/decorators.py

from functools import wraps
from flask import g, redirect, url_for


def login_required(func):
    # 保留func的信息
    @wraps(func)
    # func(a,b,c)
    # func(1,2,c=3)
    def inner(*args, **kwargs):
        if g.user:
            return func(*args, **kwargs)
        else:
            return redirect(url_for("auth.login"))

    return inner

# @login_required
# def publish_question(quesiton_id):
#     pass
#
# login_required(publish_question)(question_id)

ORM模型

demo4/model.py

from exts import db
from datetime import datetime


class UserModel(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(100), nullable=False)
    password = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(100), nullable=False, unique=True)
    join_time = db.Column(db.DateTime, default=datetime.now)


class EmailCaptchaModel(db.Model):
    __tablename__ = "email_captcha"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    email = db.Column(db.String(100), nullable=False)
    captcha = db.Column(db.String(100), nullable=False)


class QuestionModel(db.Model):
    __tablename__ = "question"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.now)

    # 外键
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    author = db.relationship(UserModel, backref="questions")


class AnswerModel(db.Model):
    __tablename__ = "answer"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    content = db.Column(db.Text, nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.now)

    # 外键
    question_id = db.Column(db.Integer, db.ForeignKey("question.id"))
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"))

    # 关系
    question = db.relationship(QuestionModel, backref=db.backref("answers", order_by=create_time.desc()))
    author = db.relationship(UserModel, backref="answers")

注册、验证码、登录相关功能

demo4/blueprints/auth.py

from flask import Blueprint, render_template, jsonify, redirect, url_for, session
from exts import mail, db
from flask_mail import Message
from flask import request
import string
import random
from models import EmailCaptchaModel
from .forms import RegisterForm, LoginForm
from models import UserModel
from werkzeug.security import generate_password_hash, check_password_hash

# /auth
bp = Blueprint("auth", __name__, url_prefix="/auth")


# bp.route:如果没有指定methods参数,默认就是GET请求
@bp.route("/captcha/email")
def get_email_captcha():
    # /captcha/email/<email>
    # /captcha/email?email=xxx@qq.com
    email = request.args.get("email")
    # 4/6:随机数组、字母、数组和字母的组合
    source = string.digits * 4
    captcha = random.sample(source, 4)
    captcha = "".join(captcha)
    # I/O:Input/Output

    # message = Message(subject="验证码", recipients=[email], body=f"您的验证码是:{captcha}")
    # mail.send(message)

    print(f"您的验证码是:{captcha}")

    # memcached/redis
    # 用数据库表的方式存储
    email_captcha = EmailCaptchaModel(email=email, captcha=captcha)
    db.session.add(email_captcha)
    db.session.commit()
    # RESTful API
    # {code: 200/400/500, message: "", data: {}}
    return jsonify({"code": 200, "message": "", "data": None})


@bp.route("/mail/test")
def mail_test():
    message = Message(subject="邮箱测试", recipients=["kruskal666@163.com"], body="这是一条测试邮件")
    mail.send(message)
    return "邮件发送成功!"


# GET:从服务器上获取数据
# POST:将客户端的数据提交给服务器
@bp.route("/register", methods=['GET', 'POST'])
def register():
    if request.method == 'GET':
        return render_template("register.html")
    else:
        # 验证用户提交的邮箱和验证码是否对应且正确
        # 表单验证:flask-wtf: wtforms
        form = RegisterForm(request.form)
        if not form.validate():
            print(form.errors)
            return redirect(url_for("auth.register"))

        email = form.email.data
        username = form.username.data
        password = form.password.data
        user = UserModel(email=email, username=username, password=generate_password_hash(password))
        db.session.add(user)
        db.session.commit()
        return redirect(url_for("auth.login"))


@bp.route("/login", methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template("login.html")
    else:
        form = LoginForm(request.form)
        if not form.validate():
            print(form.errors)
            return redirect(url_for("auth.login"))

        email = form.email.data
        password = form.password.data
        user = UserModel.query.filter_by(email=email).first()

        if not user:
            print("邮箱在数据库中不存在!")
            return redirect(url_for("auth.login"))

        if not check_password_hash(user.password, password):
            print("密码错误!")
            return redirect(url_for("auth.login"))

        # cookie:
        # cookie中不适合存储太多的数据,只适合存储少量的数据
        # cookie一般用来存放登录授权的东西
        # flask中的session,是经过加密后存储在cookie中的
        session['user_id'] = user.id
        return redirect("/")


@bp.route("/logout")
def logout():
    session.clear()
    return redirect("/")

问答模块

demo4/blueprints/qa.py

from flask import Blueprint, request, render_template, g, redirect, url_for
from .forms import QuestionForm, AnswerForm
from models import QuestionModel, AnswerModel
from exts import db
from decorators import login_required

bp = Blueprint("qa", __name__, url_prefix="/")


# http://127.0.0.1:5000
@bp.route("/")
def index():
    questions = QuestionModel.query.order_by(QuestionModel.create_time.desc()).all()
    return render_template("index.html", questions=questions)


@bp.route("/qa/publish", methods=['GET', 'POST'])
@login_required
def publish_question():
    if request.method == 'GET':
        return render_template("publish_question.html")
    else:
        form = QuestionForm(request.form)
        if not form.validate():
            print(form.errors)
            return redirect(url_for("qa.publish_question"))

        title = form.title.data
        content = form.content.data
        question = QuestionModel(title=title, content=content, author=g.user)
        db.session.add(question)
        db.session.commit()
        return render_template("detail.html", question=question)


@bp.route("/qa/detail/<qa_id>")
def qa_detail(qa_id):
    question = QuestionModel.query.get(qa_id)
    return render_template("detail.html", question=question)


# @bp.route("/answer/publish", methods=['POST'])
@bp.post("/answer/publish")
@login_required
def publish_answer():
    form = AnswerForm(request.form)
    if not form.validate():
        print(form.errors)
        return redirect(url_for("qa.qa_detail", qa_id=request.form.get("question_id")))

    content = form.content.data
    question_id = form.question_id.data
    answer = AnswerModel(content=content, question_id=question_id, author_id=g.user.id)
    db.session.add(answer)
    db.session.commit()
    return redirect(url_for("qa.qa_detail", qa_id=question_id))


@bp.route("/search")
def search():
    # /search?q=flask
    # /search/<q>
    # post, request.form
    q = request.args.get("q")
    questions = QuestionModel.query.filter(QuestionModel.title.contains(q)).all()
    return render_template("index.html", questions=questions)

表单数据验证模块

demo4/forms.py

import wtforms
from wtforms.validators import Email, Length, EqualTo, InputRequired
from models import UserModel, EmailCaptchaModel
from exts import db


# Form:主要就是用来验证前端提交的数据是否符合要求
class RegisterForm(wtforms.Form):
    email = wtforms.StringField(validators=[Email(message="邮箱格式错误!")])
    captcha = wtforms.StringField(validators=[Length(min=4, max=4, message="验证码格式错误!")])
    username = wtforms.StringField(validators=[Length(min=3, max=20, message="用户名格式错误!")])
    password = wtforms.StringField(validators=[Length(min=6, max=20, message="密码格式错误!")])
    password_confirm = wtforms.StringField(validators=[EqualTo("password", message="两次密码不一致!")])

    # 自定义验证:
    # 1. 邮箱是否已经被注册
    def validate_email(self, field):
        email = field.data
        user = UserModel.query.filter_by(email=email).first()
        if user:
            raise wtforms.ValidationError(message="该邮箱已经被注册!")

    # 2. 验证码是否正确
    def validate_captcha(self, field):
        captcha = field.data
        email = self.email.data
        captcha_model = EmailCaptchaModel.query.filter_by(email=email, captcha=captcha).first()
        if not captcha_model:
            raise wtforms.ValidationError(message="邮箱或验证码错误!")
        # else:
        #     # todo:可以删掉captcha_model
        #     db.session.delete(captcha_model)
        #     db.session.commit()


class LoginForm(wtforms.Form):
    email = wtforms.StringField(validators=[Email(message="邮箱格式错误!")])
    password = wtforms.StringField(validators=[Length(min=6, max=20, message="密码格式错误!")])


class QuestionForm(wtforms.Form):
    title = wtforms.StringField(validators=[Length(min=3, max=100, message="标题格式错误!")])
    content = wtforms.StringField(validators=[Length(min=3, message="内容格式错误!")])


class AnswerForm(wtforms.Form):
    content = wtforms.StringField(validators=[Length(min=3, message="内容格式错误!")])
    question_id = wtforms.IntegerField(validators=[InputRequired(message="必须要传入问题id!")])

模板及静态文件

概念

g和session

都是用于在请求处理过程中共享数据的机制,但它们有不同的作用和使用场景。

  • g:适用于在同一个请求处理周期中需要共享数据的情况
  • Session:适用于跨请求存储用户会话信息的情况

cookie和session

  • cookie:在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用cookie只能存储一些小量的数据。
  • session: session和cookie的作用有点类似,都是为了存储用户相关的信息。不同的是,cookie是存储在本地浏览器,而session存储在服务器,不同的服务器,不同的框架,不同的语言有不同的实现。虽然实现不一样,但是他们的目的都是服务器为了方便存储数据的。session的出现,是为了解决cookie存储数据不安全的问题的。

cookie和session结合使用:web开发发展至今,cookie和session的使用已经出现了一些非常成熟的方案。在如今的市场或者企业里,一般有两种存储方式:

  1. 存储在服务端:通过cookie存储一个session_id,然后具体的数据则是保存在session中。如果用户已经登录,则服务器会在cookie中保存一个session_id,下次再次请求的时候,会把该session_id携带上来,服务器根据session_id在session库中获取用户的session数据。就能知道该用户到底是谁,以及之前保存的一些状态信息。这种专业术语叫做server side session。存储在服务器的数据会更加的安全,不容易被窃取。但存储在服务器也有一定的弊端,就是会占用服务器的资源,但现在服务器已经发展至今,一些session信息还是绰绰有余的。

  2. 将session数据加密,然后存储在cookie中。这种专业术语叫做client side session。flask采用的就是这种方式,但是也可以替换成其他形式。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值