2025最新Flask学习笔记(对照Django做解析)

前言:如果还没学Django的同学,可以看Django 教程 | 菜鸟教程,也可以忽略下文所提及的Django内容;另外,由于我们接手的项目大多都是前后端分离的项目,所以本文会跳过对模板的介绍,感兴趣的朋友可以自行查阅其他相关资料;

Flask快速上手

创建项目:

相较于Django而已,Flask的学习比较轻松,在构建视图、路由等方面也是简洁很多,上面代码就是一个简单的接口,可以直接右键当前文件运行:

在浏览器访问http://127.0.0.1:5000 就可以看到输出的内容:

上面代码对应的Django代码如下:

# myapp/views.py
from django.http import HttpResponsedef hello_world(request):return HttpResponse("Hello World")#myapp/urls.pyfrom django.urls import path
from . import viewsurlpatterns = [path('', views.hello_world, name='hello_world'),
]# urls.py
from django.contrib import admin
from django.urls import include, pathurlpatterns = [path('admin/', admin.site.urls),path('', include('myapp.urls')), # 包含myapp的urls
]

Flask路由

Flask中的route()装饰器用于将URL绑定到函数。例如:

@app.route('/hello')
def hello_world():return 'hello world'

在这里,URL '/ hello' 规则绑定到hello_world()函数。 

因此,如果用户访问http://localhost:5000/hello hello_world()函数的输出将在浏览器中呈现。

另外使用add_url_rule()函数也可用于将URL与函数绑定,如下所示:

def hello_world():return 'hello world'
app.add_url_rule('/nihao', 'hello', hello_world)

以下是 add_url_rule 方法的主要参数说明:

  • rule: 这是一个字符串,表示URL规则。例如,'/'代表根路径。
  • endpoint (可选): 标识这个URL规则的名称(相当于唯一标识这个视图的名字,因为后续视图多了,有可能出现重名,就可以通过endpoint来标明,类似于Djnago中的路由命名),默认是视图函数的名字。这个值用于反向生成URL,比如通过 url_for() 函数。
  • view_func (可选): 一个函数或方法,一旦匹配到相应的URL规则就会被调用执行。这个参数通常是你的视图函数。

跟Django有所不同,Django的路由是通过单独的urls文件注册,如下:

from django.urls import path
from . import viewsurlpatterns = [path('', views.hello_world, name='hello_world'),
]

当你要构建动态URL时,此变量部分标记为<variable-name> 。它作为关键字参数传递给与规则相关联的函数。在以下示例中,route()装饰器的规则参数包含附加到URL '/hello' <name>。 因此,如果在浏览器中输入http://localhost:5000/hello/mm作为URL,则'mm'将作为参数提供给 hello()函数。

from flask import Flask
app = Flask(__name__)@app.route('/hello/<name>')  #<name>默认的传值类型是字符串类型
def hello_name(name):return 'Hello %s!' % nameif __name__ == '__main__':app.run()

在 Flask 路由中,路径参数 <name> 默认是作为字符串类型处理的。然而,Flask 允许你指定路径参数的转换器(converter),从而可以接受不同类型的值。以下是 Flask 支持的一些内置转换器以及它们对应的类型:

  • string: (默认类型)接受任何不包含斜杠的文本,例如 "/hello/world" 中的 "world"。
  • int: 接受正整数,并将其作为整数类型传递给视图函数,例如 "/hello/123" 会将 123 作为整数传入。
  • float: 接受正浮点数,例如 "/hello/123.45" 会将 123.45 作为浮点数传入。
  • path: 类似于 string,但它也接受包含斜杠的文本,例如 "/hello/a/b/c" 可以匹配并传入 "a/b/c"。
  • uuid: 接受符合 UUID 格式的字符串,例如 "/hello/6eade98b-7dce-4c62-bf6f-ccbe9cf95bc1"。UUID 是一种标准格式用于定义通用唯一标识符。
  • any: 匹配多个预定义的值中的任意一个。你需要提供这些值作为参数,用逗号分隔。例如,<any(abc,def):name> 只接受 "abc" 或 "def" 作为有效的参数值。

使用这些转换器时,只需在路径参数名称前加上转换器名称和冒号,如 <int:id> 或 <float:number>。

Django中构建动态路由的方法:

urlpatterns = [re_path('^index/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})$',views.index,name='index')
]from django.urls import path,include
urlpatterns = [    path('app01/',include(('app01.urls','app01'),namespace='app01'))]# views.pyt.
def index(request,year,month,day):args = ['2023','12','31']return HttpResponse(resolve(reverse('app01:index',args=args)))

另外,在Flask中使用app.route()注册路由时,默认只支持get方法,要想支持post或其他方法,就得使用method参数说明,如下:

@app.route('/login',methods = ['POST', 'GET'])
def login():if request.method == 'POST':print(1)user = request.form['mm']return redirect(url_for('success',name = user))else:print(2)name = request.args.get("name")return name

 这里需要注意的是:request.form()方法是用于获取前端表单POST传过来的数据,而request.args.get()是用于获取请求的各种信息,比如请求方法、GET方法表单数据、URL参数等。例如,在浏览器访问127.0.0.1:5000/login?name=John&age=25&city=New+York,request.args.get("name")获取的值就是John:

补充:Flask中的Request对象重要属性如下所列:

  • Form - 它是一个字典对象,包含表单参数及其值的键和值对。

  • args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。

  • Cookies  - 保存Cookie名称和值的字典对象。

  • files - 与上传文件有关的数据。

  • method - 当前请求方法。

拓展:Flask不像Django一样,Flask的Request对象是通过上下文管理获取的,需要导入使用,如:from flask import  request

Url构建

在Flask中,url_for()函数用来构建特定函数的url,有点类似于Django中的reverse()函数;url_for()函数接受函数的名称作为第一个参数,以及一个或多个关键字参数,每个参数对应于URL的变量部分,如下例子:

from flask import Flask, redirect, url_for
app = Flask(__name__)@app.route('/teacher')
def hello_teacher():return 'Hello teacher'@app.route('/student/<stu_name>')def hello_student(stu_name):return 'Hello %s' % stu_name@app.route('/user/<name>')
def hello_user(name):if name =='teacher':return redirect(url_for('hello_teacher'))else:return redirect(url_for('hello_student', stu_name = name))if __name__ == '__main__':app.run(debug = True)

当运行后,在浏览器中访问127.0.0.1:5000/student/小明 

其中“小明”会作为参数传入到hello_user(name)中,经过if判断后,重定向到hello_student(stu_name)函数

这里的url_for('hello_student', stu_name = name)生成的路由是/hello_student/<stu_name>

Django中与之对应的函数是reverse(),用法如下:

reverse通过路由命名或可调用的视图对象来生成相应的路由地址
resolve通过路由地址获取路由对象的信息

from django.http import HttpResponse
from django.shortcuts import render,reverse
from django.urls import resolve#urls.py
from django.urls import path,re_path
from . import views
urlpatterns = [re_path('^index/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})$',views.index,name='index')
]from django.urls import path,include
urlpatterns = [    path('app01/',include(('app01.urls','app01'),namespace='app01'))]# views.pyt.
def index(request,year,month,day):args = ['2023','12','31']return HttpResponse(resolve(reverse('app01:index',args=args)))#reverse('app01:index',args=args)  app01/index/2023/12/31#resolve(reverse('app01:index',args=args)) 
#ResolverMatch(func=app01.views.index, args=(), kwargs={'year': '2023', 'month': '12', 'day': '31'}, url_name=index, app_names=['app01'], namespaces=['app01'], route=app01/index/(?P[0-9]{4})/(?P[0-9]{2})/(?P[0-9]{2})$)

Cookie/Session

from flask import Flask, make_response, request # 注意需导入 make_responseapp = Flask(__name__)
app.secret_key = 'asdfgsdfsfasdfsdvzfbstrjthgraeg'  #记得配上,不然用session的时候会报错@app.route("/set_cookies")
def set_cookie():resp = make_response("success")resp.set_cookie("w3cshool", "w3cshool",max_age=3600)return resp@app.route("/get_cookies")
def get_cookie():cookie_1 = request.cookies.get("w3cshool")  # 获取名字为Itcast_1对应cookie的值return cookie_1@app.route("/delete_cookies")
def delete_cookie():resp = make_response("del success")resp.delete_cookie("w3cshool")return resp# 设置session
@app.route("/set_session")
def set_session():session['key'] = 'value'  # 在会话中存储数据return 'Session set'# 获取session
@app.route("/get_session")
def get_session():value = session.get('key', 'Not set')  # 获取会话中的数据return value# 删除session
@app.route("/delete_session")
def delete_session():session.pop('key', None)  # 从会话中删除数据return 'Session deleted'if __name__ == '__main__':app.run(debug=True)

 abort()函数

在Flask中,abort 函数用于提前终止请求并返回一个HTTP错误状态码给客户端。它通常用于处理异常情况或错误条件,比如当资源未找到、权限不足等情况下返回相应的HTTP错误码。

abort 函数可以接受一个HTTP状态码作为参数,并且可以选择性地提供一个描述信息或者自定义响应体。Flask会将这个状态码转换为对应的HTTP错误页面。如果想要自定义错误页面的显示内容,可以通过Flask的 errorhandler 装饰器来实现。

下面是一个简单的例子,演示了如何使用 abort 来返回404(Not Found)和403(Forbidden)错误:

from flask import Flask, abortapp = Flask(__name__)@app.route('/resource/<int:resource_id>')
def get_resource(resource_id):if resource_id != 1:# 如果资源ID不是1,则返回404错误abort(404)else:return f'Resource with ID {resource_id}'@app.route('/access/<string:permission>')
def check_access(permission):if permission != 'admin':# 如果权限不是admin,则返回403错误abort(403)else:return 'Access Granted'if __name__ == '__main__':app.run(debug=True)

 你还可以通过 errorhandler 装饰器来自定义不同HTTP错误码的错误页面:

from flask import Flask, abort, render_template_stringapp = Flask(__name__)@app.errorhandler(404)
def page_not_found(error):# 自定义404错误页面return render_template_string('<h1>404 - Not Found</h1>'), 404@app.errorhandler(403)
def forbidden(error):# 自定义403错误页面return render_template_string('<h1>403 - Forbidden</h1>'), 403# 前面提到的路由函数
@app.route('/resource/<int:resource_id>')
def get_resource(resource_id):if resource_id != 1:abort(404)else:return f'Resource with ID {resource_id}'@app.route('/access/<string:permission>')
def check_access(permission):if permission != 'admin':abort(403)else:return 'Access Granted'if __name__ == '__main__':app.run(debug=True)

文件上传

在 Flask 中处理文件上传非常简单。它需要一个 HTML 表单,其 ​enctype​ 属性设置为“​multipart/form-data”​,将文件发布到 URL。

URL 处理程序从 ​request.files[]​ 对象中提取文件,并将其保存到所需的位置。

每个上传的文件首先会保存在服务器上的临时位置,然后将其实际保存到它的最终位置。

目标文件的名称可以是硬编码的,也可以从 ​request.files[file] ​对象的​ filename ​属性中获取。但是,建议使用 ​secure_filename()​ 函数获取它的安全版本。

可以在 Flask 对象的配置设置中定义默认上传文件夹的路径和上传文件的最大大小。

app.config['UPLOAD_FOLDER'] 定义上传文件夹的路径 
app.config['MAX_CONTENT_LENGTH'] 指定要上传的文件的最大大小(以字节为单位)

先来看个简单的例子:

首先,你需要一个HTML表单让用户可以选择并上传文件。这里是一个使用POST方法和enctype="multipart/form-data"属性的基本表单示例:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Upload File</title>
</head>
<body><form action="/upload" method="post" enctype="multipart/form-data"><input type="file" name="file"><input type="submit"></form>
</body>
</html>

接下来,在你的Flask应用中,编写处理文件上传的视图函数:

from flask import Flask, request, redirect, url_for, render_template, flash
import os
from werkzeug.utils import secure_filenameapp = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'  # 设置上传文件存放的路径
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 限制文件大小为16MB# 确保保存上传文件目录存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)@app.route('/upload', methods=['GET', 'POST'])
def upload_file():if request.method == 'POST':# 检查是否有一个名为file的文件部分if 'file' not in request.files:flash('No file part')return redirect(request.url)file = request.files['file']# 如果用户没有选择文件,则浏览器也会提交一个空的file部分if file.filename == '':flash('No selected file')return redirect(request.url)if file:filename = secure_filename(file.filename)  # 安全地获取文件名file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))return redirect(url_for('upload_file', filename=filename))return render_template('upload.html')  # 假设你将上面的HTML放在templates/upload.html中if __name__ == '__main__':app.secret_key = 'your_secret_key'  # 设置secret key用于flash消息app.run(debug=True)

启动应用,选择文件并上传:

提交后,项目目录下的upload文件夹多了刚刚上传的文件:

数据库操作

由于Flask不直接支持ORM操作,因此需要额外下载扩展。在Flask应用中进行ORM(对象关系映射)操作,最常用的库是SQLAlchemy。SQLAlchemy是一个功能强大的Python SQL工具包和ORM,它允许你以面向对象的方式与数据库交互。

pip install Flask-SQLAlchemy

pip install pymysql

 以下是SQLAlchemy的配置以及简单用法

from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@localhost/flask_test'
# 禁用追踪修改以节省内存
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app)class User(db.Model):__tablename__ = 'user'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 to_dict(self):return {'id': self.id, 'username': self.username, 'email': self.email}@app.route('/add', methods=['POST'])
def add_user():"""添加用户:return: """username = request.json.get('username')email = request.json.get('email')new_user = User(username=username, email=email)db.session.add(new_user)db.session.commit()return jsonify(new_user.to_dict()), 201@app.route('/users', methods=['GET'])
def get_users():"""获取用户:return: """users = User.query.all()return jsonify([user.to_dict() for user in users])@app.route('/user/<int:user_id>', methods=['PUT'])
def update_user(user_id):"""更新用户:return: """user = User.query.get_or_404(user_id)user.email = request.json.get('email')db.session.commit()return jsonify(user.to_dict())@app.route('/user/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):"""删除用户:return: """user = User.query.get_or_404(user_id)db.session.delete(user)db.session.commit()return '', 204if __name__ == '__main__':with app.app_context():db.create_all()  # 创建表结构app.run(debug=True)

注意:代码中的db.create_all() 是用来创建表结构的,但是如果当你定义的模型类有所改变,你再次执行db.create_all() 是检测不到的,举个例子:

class User(db.Model):
    __tablename__ = 'user'
    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)

这是你原本的模型代码,当你新增或减少了一个字段,然后你再去执行db.create_all()的时候,此时你的表结构并没有发生什么改变,那么这时候你就得借助第三方的一个扩展:

flask-migrate

pip install flask-migrate

下载之后有三个命令需要执行:

 flask db init   #只需要运行一次

 flask db upgrade #生成迁移脚本,后续有表结构发生改变(或新增表),也要运行一次
 flask db migrate #运行迁移脚本,后续表结构发生改变(或新增表),也需要运行一次
 

 Flask-SQLAlchemy高级用法

Flask-SQLAlchemy 提供了强大的 ORM(对象关系映射)功能,可以帮助你更方便地进行数据库操作。除了基本的增删改查操作外,它还支持许多高级用法,如复杂查询、关联查询、事务管理等。以下是一些 Flask-SQLAlchemy 的高级用法示例:

1. 复杂查询

使用 `filter` 和 `filter_by`

- `filter_by` 更适合用于简单的等值匹配查询。

# 查找名字为 'Liming' 的用户
users = User.query.filter_by(name='Liming').all()

- `filter` 提供了更多的灵活性,支持复杂的条件表达式。

# 查找名字为 'Liming' 且邮箱包含 'example.com' 的用户
users = User.query.filter(User.name == 'Liming', User.email.like('%example.com%')).all()

 使用 `join` 进行关联查询

假设你有两个模型 `User` 和 `Post`,其中 `Post` 模型有一个外键指向 `User` 模型。

class Post(db.Model):id = db.Column(db.Integer, primary_key=True)title = db.Column(db.String(80), nullable=False)body = db.Column(db.Text, nullable=False)user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)user = db.relationship('User', backref=db.backref('posts', lazy=True))# 查询所有用户的帖子
results = db.session.query(User, Post).join(Post).all()
for user, post in results:print(user.name, post.title)

2. 分页查询

分页查询在处理大量数据时非常有用。

page = request.args.get('page', 1, type=int)
per_page = 10  # 每页显示的数量
pagination = User.query.paginate(page, per_page, error_out=False)
users = pagination.items

3. 事务管理

使用 `db.session.commit()` 和 `db.session.rollback()` 来手动管理事务。

try:user1 = User(name='John', email='john@example.com')user2 = User(name='Jane', email='jane@example.com')db.session.add_all([user1, user2])db.session.commit()
except:db.session.rollback()raise

4. 使用 `hybrid_property` 创建动态属性

`hybrid_property` 可以让你创建一个既可以作为类方法也可以作为实例属性使用的属性。

from sqlalchemy.ext.hybrid import hybrid_propertyclass User(db.Model):id = db.Column(db.Integer, primary_key=True)first_name = db.Column(db.String(50))last_name = db.Column(db.String(50))@hybrid_propertydef full_name(self):return f"{self.first_name} {self.last_name}"

5. 自定义查询构造器

通过继承 `Query` 类并自定义查询构造器来扩展查询能力。

from flask_sqlalchemy import BaseQueryclass UserQuery(BaseQuery):def search_by_name(self, name):return self.filter(User.name.like(f'%{name}%'))db.Query = UserQuery# 使用自定义的查询构造器
users = User.query.search_by_name('Li').all()

6. 聚合函数

SQLAlchemy 支持多种聚合函数,如 `count`, `sum`, `avg` 等。

from sqlalchemy import func# 计算用户数量
user_count = db.session.query(func.count(User.id)).scalar()# 计算年龄总和
age_sum = db.session.query(func.sum(User.age)).scalar()

这些只是 Flask-SQLAlchemy 高级用法的一部分。根据你的具体需求,还可以探索更多功能,比如事件监听、索引、唯一约束等。掌握这些高级用法可以让你更加高效地构建和维护复杂的数据库应用。

类视图CBV

上面介绍的用法都是基于函数视图的,比如:

@app.route('/hello')
def hello_world():return 'hello world'

这种写法比较简单,但是不利于扩展,下面介绍基于面向对象的方法来实现视图;在 Flask 中,基于类的视图(Class-Based Views)通过 flask.views.View 和 flask.views.MethodView 提供了组织视图逻辑的另一种方式。相比于函数视图,类视图可以更好地支持代码重用、继承和扩展。以下是关于如何使用这些类视图的详细说明:

flask.views.View

from flask import Flask, views, requestapp = Flask(__name__)class MyView(views.View):def dispatch_request(self):return f"Hello, method used: {request.method}"app.add_url_rule('/myview', view_func=MyView.as_view('myview'))if __name__ == '__main__':app.run(debug=True)

添加额外参数
如果你需要向类视图传递一些初始化参数,可以通过 as_view 方法完成。这在需要根据不同上下文初始化视图时非常有用。

class GreetingView(views.View):def __init__(self, greeting_message):self.greeting_message = greeting_messagedef dispatch_request(self):return self.greeting_messagegreeting_view = GreetingView.as_view('greeting_view', greeting_message='Hello, world!')
app.add_url_rule('/greet', view_func=greeting_view)

构建动态路由以及添加装饰器

def log_access(f):@wraps(f)def decorated_function(*args, **kwargs):print("Accessing the view...")return f(*args, **kwargs)return decorated_functionclass GreetingView(MethodView):decorators = [log_access] #添加装饰器def get(self, name=None):print(111)if name:return f"Hello, {name}!"return f"Hello, {name}!"app.add_url_rule('/greet/', defaults={'name': "PMJ"}, view_func=GreetingView.as_view('greet'))
#构建动态路由
app.add_url_rule('/greet/<name>', view_func=GreetingView.as_view('greet_name'))

flask.views.MethodView

from flask import Flask, jsonify, request, viewsapp = Flask(__name__)class UserAPI(views.MethodView):def get(self, user_id):if user_id is None:# 返回用户列表return jsonify([{'id': 1, 'name': 'John Doe'}, {'id': 2, 'name': 'Jane Doe'}])else:# 返回单个用户的详细信息return jsonify({'id': user_id, 'name': 'John Doe'})def post(self):# 创建新用户data = request.get_json()return jsonify({'id': 3, 'name': data['name']}), 201def put(self, user_id):# 更新用户信息data = request.get_json()return jsonify({'id': user_id, 'name': data['name']})def delete(self, user_id):# 删除用户return '', 204# 将 URL 规则和视图类关联起来
user_view = UserAPI.as_view('user_api')# 定义路由规则
app.add_url_rule('/users/', defaults={'user_id': None}, view_func=user_view, methods=['GET'])
app.add_url_rule('/users/', view_func=user_view, methods=['POST'])
app.add_url_rule('/users/<int:user_id>', view_func=user_view, methods=['GET', 'PUT', 'DELETE'])if __name__ == '__main__':app.run(debug=True)

蓝图

Flask中的蓝图类似于Django中的app,都是为了更好的应用解耦,比如一个系统有订单模块、用户模块、商品模块等,就可以将它们分别创建一个蓝图来管理。如下:

文件对应代码: 

#Order/views.py#函数视图版本
from flask import Blueprintorder = Blueprint('order', __name__)@order.route('/f1')
def f1():return 'f1'#类视图版本
from flask import Blueprint, viewsorder = Blueprint('order', __name__)class F1View(views.MethodView):def get(self):return 'f1'# 添加 URL 规则
order.add_url_rule('/f1', view_func=F1View.as_view('f1'))
#User/views/py#函数视图版本
from flask import Blueprintuser = Blueprint('user', __name__)@user.route('/f2')
def f2():return 'f2'#类视图版本
from flask import Blueprint, viewsuser = Blueprint('user', __name__)class F2View(views.MethodView):def get(self):return 'f2'# 添加 URL 规则
user.add_url_rule('/f2', view_func=F2View.as_view('f2'))
#lantu/app.pyfrom flask import Flaskfrom lantu.Order.views import order
from lantu.User.views import userdef create_app():app = Flask(__name__)#注册蓝图app.register_blueprint(order, url_prefix='/order')app.register_blueprint(user, url_prefix='/user')return app
#manage.pyfrom lantu.app import create_appif __name__ == '__main__':app = create_app()app.run(debug=True)

启动之后访问:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72239.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自然语言处理NLP入门 -- 第十一节NLP 实战项目 3: 文本摘要

1. 为啥需要文本摘要&#xff1f; 还记得小时候我们要写“读后感”或“观后感”吗&#xff1f;看完一篇长长的文章、一本书&#xff0c;甚至一部电影后&#xff0c;老师总是要我们用几句话概括主要内容。其实&#xff0c;这就跟文本摘要的核心思路一样——把那些最有价值、最能…

算法day4 dfs搜索2题

一 糖果 我们看这个蓝桥A组真题 首先我们看这个题目说有M种的糖果&#xff0c;K颗一包&#xff0c;N包糖果 第一行就是输入M&#xff0c;K&#xff0c;N的数量 后面就是输入每个糖果在每包里面的种类 然后问我们最少要用几包糖果才可以把所有种类的糖果都吃一遍 如果不可以吃完…

【MySQL】窗口函数详解(概念+练习+实战)

文章目录 前言1. SQL窗口函数 1.1 窗口函数概念1.2 窗口函数语法1.3 常见窗口函数 1.3.1 聚合窗口函数1.3.2 专用窗口函数 1.4 窗口函数性能比较 2. LeetCode 例题 2.1 LeetCode SQL 178&#xff1a;分数排名2.2 LeetCode SQL 184&#xff1a;最高工资2.3 LeetCode SQL 185&am…

【Ai】--- DeepSeek-r1 如何选择适合自己的版本(超详细)

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【Ai】--- DeepSeek-r1 如何选择适合自己…

植物大战僵尸金铲铲版 v1.1.6(windows+安卓)

游戏简介 《植物大战僵尸金铲铲版》是由“古见xzz”、“对不起贱笑了”、“是怪哉吖”等联合开发的民间魔改版本&#xff0c;融合了原版塔防玩法与《金铲铲之战》的自走棋元素&#xff0c;属于非官方同人作品。 游戏特点 合成升星机制&#xff1a;三个相同低星植物可合成更高…

网络空间安全(6)web应用程序技术

前言 Web应用程序技术是指用于开发和构建基于Web的应用程序的技术和工具&#xff0c;涵盖了前端开发、后端开发、数据库管理、安全性等多个方面的技术。 一、前端开发技术 HTML/CSS/JavaScript&#xff1a;HTML用于构建网页结构&#xff0c;CSS用于进行样式设计&#xff0c;Jav…

零基础学习OpenGL(一)创建一个窗口

基于 ubuntu 系统&#xff0c;设置基础环境。 #!/usr/bin/env bashsudo apt-get update# 安装基础编译软件 sudo apt-get -y install gcc g cmake git# 安装编译 glfw 依赖的软件 sudo apt-get -y install libwayland-dev libx11-dev libxcursor-dev libxi-dev libxinerama-de…

Windows 11 下正确安装 Docker Desktop 到 D 盘的完整教程

文章目录 Windows 11 在 D 盘正确安装 Docker Desktop 的完整教程**前言****准备工作****1. 手动创建 Docker 相关目录**&#xff08;⚠️ **这一步非常重要**&#xff0c;否则会报错&#xff09;**2. 下载 Docker Desktop 安装程序****3. 使用管理员权限打开终端** **安装 Doc…

版图自动化连接算法开发 00001 ------ 直接连接两个给定的坐标点

版图自动化连接算法开发 00001 ------ 直接连接两个给定的坐标点 引言正文定义坐标点的类绘图显示代码直接连接两个坐标点引言 由于人工智能的加速普及,每次手动绘制版图都会觉得特别繁琐,作者本人在想可否搞一个自动化连接器件端口的算法,后期可以根据一些设定的限制进行避…

AIP-156 单例资源

编号156原文链接AIP-156: Singleton resources状态批准创建日期2019-05-12更新日期2024-04-15 API有时需要表示在任意上级资源中&#xff0c;始终只存在一个实例的资源。常见的例子是配置对象。 指南 API 可以 定义 单例资源 。单例资源 必须 始终随上级资源而存在&#xff…

程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图(水文,勿三)

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。 这一节我们来学习指针的相关知识&#xff0c;学习内存和地址&#xff0c;指针变量和地址&#xff0c;包…

【实用技巧】RAGFlow+DeepSeek搭建私人Ai助理

前言 满血版DeepSeek虽然很好用&#xff0c;但仍然有三个主要缺陷&#xff1a; 联网的DeepSeek无法解决数据安全问题&#xff0c;如果使用&#xff0c;数据将传输到其服务器&#xff0c;数据隐私性无法保证。上传的文件存在限制&#xff0c;无法解决有多个文件的问题。回答的…

Storm实时流式计算系统(全解)——中

storm编程的基本概念-topo-spout-bolt 例如下&#xff1a; storm 编程接口-spout的结构及组件实现 storm编程案例-spout组件-实现 这是我的第一个组件&#xff08;spout组件继承BaseRichSput&#xff09;所有重写内部的三个方法&#xff0c;用于接收数据&#xff08;这里数据是…

【tplink】校园网接路由器如何单独登录自己的账号,wan-lan和lan-lan区别

老式路由器TPLINK&#xff0c;接入校园网后一人登录&#xff0c;所有人都能通过连接此路由器上网&#xff0c;无法解决遂上网搜索&#xff0c;无果&#xff0c;幸而偶然看到一个帖子说要把信号源网线接入路由器lan口&#xff0c;开启新世界。 一、wan-lan&#xff0c;lan-lan区…

Qt常用控件之旋钮QDial

旋钮QDial QDial 表示一个旋钮控件。 1. QDial属性 属性说明value当前数值。minimum最小值。maximum最大值。singleStep按下方向键时改变的步长。pageStep按下 pageUp/pageDown 的时候改变的步长。sliderPosition界面上旋钮显示的初始位置。tracking外观是否会跟踪数值变化&…

微服务笔记 2025/2/15

微服务是一种软件架构风格&#xff0c;它是以专注于单一职责的很多小型项目为基础&#xff0c;组合出复杂的大型应用。 微服务是一种架构。 微服务是一种架构。 微服务是一种架构。 以前自己做项目最常用的架构是单体架构。单体项目不适合开发大型项目。 学习微服务技术来解…

7-1JVMCG垃圾回收

一、GC的作用与原理 ​核心功能​ 自动识别并回收堆内存中不再被引用的对象&#xff0c;释放内存空间。 避免手动管理内存的复杂性&#xff08;如C/C中的delete/free操作&#xff09;&#xff0c;降低内存泄漏风险。 ​判断对象可回收的方法​ ​可达性分析算法&#xff1a;…

yunedit-post ,api测试比postman更好

postman应该是大家最熟悉的api测试软件了&#xff0c;但是由于它是外国软件&#xff0c;使用它的高端功能注册和缴费都比较麻烦。生成在线文档分享也经常无法访问被拦截掉。 这里可以推荐一下yunedit-post&#xff0c;该有的功能都有。 https://www.yunedit.com/postdetail …

010 rocketmq批量消息

文章目录 批量消息BatchProducer.javaBatchConsumer.java 批量消息 批量发送可以提⾼发送性能&#xff0c;但有⼀定的限制&#xff1a; topic 相同 waitStoreMsgOK 相同 &#xff08;⾸先我们建设消息的iswaitstoremsgoktrue(默认为true), 如果没有异常,我们将始终收到"O…

6.6.6 嵌入式SQL

文章目录 2个核心问题识别SQL语句主语言和SQL通信完整导图 2个核心问题 SQL语句嵌入高级语言需要解决的2个核心问题是&#xff1a;如何识别嵌入语句&#xff1f;如何让主语言&#xff08;比如C,C语言&#xff09;和SQL通信&#xff1f; 识别SQL语句 为了识别主语言中嵌入的SQL…