我正在学习针对 Web 开发人员的 Python 课程,目前正在处理 Flask。最近,我的讲师从我那里得到了一项任务,即借助查询参数为端点“/events”创建搜索功能。我几乎不知道我应该从什么开始,以及我是否应该在这种情况下使用 WTF-Forms。下面发布了更详细的代码(我的尝试)。
--->这是我的数据库:
class Event(db.Model):
id = db.Column(db.Integer, primary_key=True, nullable=False)
title = db.Column(db.Text, nullable=False)
description = db.Column(db.Text, nullable=False)
created_by = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
begin_at = db.Column(db.Date, nullable=False)
end_at = db.Column(db.Date, nullable=False)
max_users = db.Column(db.Integer, nullable=False)
is_active = db.Column(db.Boolean, default=False, server_default="false")
--->有一个搜索表格:
class SearchForm(FlaskForm):
search_event_by_title = StringField(label="Search event by title", validators=[DataRequired()])
submit = SubmitField(label="Search", validators=[DataRequired()])
---> 有一个“视图”:
@app.route("/events", methods=["GET", "POST"])
@login_required
def event_list():
query = db.select(Event.id, Event.title)
events = db.session.execute(query)
context = {
"events": events
}
form = SearchForm()
if form.validate_on_submit():
search_title = request.form.get('title')
result = Event.query.filter_by(title=search_title).all()
return render_template("event/list.html", result=result)
return render_template("event/list.html", **context, form=form)
“/events”默认显示事件列表(链接),我需要在此页面实现搜索功能,以便在搜索栏过滤数据库查询中输入并呈现正确的输出。我真的不知道如何将查询参数与表单连接起来(如果这里需要的话;我们也可以不使用它)并以正确的方式查询数据库 - 必须按“标题”条件搜索和过滤“事件”。当前代码什么也不做。在“事件”数据库中的现有标题“event/list.html”进行搜索尝试后,该模板不断显示完整的事件列表,忽略过滤。
---> 有html文件(可能主要错误在这里):
{% extends "base.html" %}
{% block content %}
<h1>Events list</h1>
<form action="{{ url_for('event_list') }}" method="POST">
{{ csrf_token }}
{{ form.search_event_by_title }}
{{ form.submit }}
{% for item in result%}
{{ item.title }}
{% endfor %}
<ul>
{% for item in events %}
<li><a href="{{url_for('event_detail', id=item.id)}}">{{ item.id }}: {{ item.title }}</a></li>
{% endfor %}
</ul>
</form>
{% endblock %}
请帮忙。我真的需要弄清楚:(
如果要使用查询参数,则不需要使用POST方法传输。输入字段的名称和值会自动附加到 URL,并且当您使用 GET 时,可以使用
request.args
在服务器上请求。
我认为 WTForms 对于此目的来说不是最佳的,也不是必需的。
此示例向您展示了在事件中搜索标题的简化版本。
from flask import (
Flask,
render_template,
request
)
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import (
Integer,
String,
Text
)
from sqlalchemy.orm import (
DeclarativeBase,
Mapped,
mapped_column,
)
app = Flask(__name__)
app.config.from_mapping(
SQLALCHEMY_DATABASE_URI='sqlite:///sample.db'
)
class Base(DeclarativeBase):
pass
db = SQLAlchemy(app, model_class=Base)
class Event(db.Model):
__tablename__ = 'events'
id: Mapped[int] = mapped_column(Integer, primary_key=True)
title: Mapped[str] = mapped_column(Text, nullable=False)
with app.app_context():
db.create_all()
events = [Event(title=f'title-{i}') for i in range(1, 11)]
db.session.add_all(events)
db.session.commit()
@app.route('/')
def index():
qs = request.args.get('qs')
stmt = db.select(Event)
if qs:
stmt = stmt.where(Event.title.ilike(f'%{qs}%'))
events = db.session.execute(stmt).scalars()
return render_template('index.html', **locals())
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index</title>
</head>
<body>
<form>
<input type="text" name="qs" />
<button type="submit">Search</button>
</form>
<ul>
{% for event in events -%}
<li>{{ event.title }}</li>
{% endfor -%}
</ul>
</body>
</html>
您部分使用旧查询接口和关联的方式来定义模型。程序还是一样的。
def index():
qs = request.args.get('qs')
query = Event.query
if qs:
query = query.filter(Event.title.ilike(f'%{qs}%'))
events = query.all()
return render_template('index.html', **locals())