flask简博客开发(3)

 实验知识点

  • 编写视图部分
  • 编写模板部分
  • 运行应用

现在数据库连接已经正常工作,可以开始编写视图函数。我们需要四个视图函数:

显示条目

这个视图显示所有存储在数据库中的条目。它监听着应用的根地址以及将会从数据库中查询标题和内容。id值最大的条目(最新的条目)将在最前面。从游标返回的行是按select语句中声明的列组织的元组。对于像我们这样的小应用是足够的,但是你可能要把它们转换成字典,如果你对如何转换成字典感兴趣的话,请查阅简化查询

例子。

视图函数将会把条目作为字典传入show_entries.html 模板并返回渲染结果。

flaskr/simp_blog.py 文件中添加如下代码:

@app.route('/')
def show_entries():
    cur = g.db.execute('select title, text from entries order by id desc')   # 查询语句
    entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]   # 将查询结果转换为字典
    return render_template('show_entries.html', entries=entries)

添加新条目:

这个视图允许登录的用户添加新的条目。它只回应POST请求,实际的表单是显示在show_entries页面。如果正常工作的话,我们用flash()向下一个请求闪现一条信息并且跳转回show_entries页面。

@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)
    g.db.execute('insert into entries (title, text) values (?, ?)',[request.form['title'], request.form['text']])   # 向数据库中插入数据
    g.db.commit()   # 更新数据
    flash('New entry was successfully posted')   # 闪现一条消息
    return redirect(url_for('show_entries'))

注意我们这里检查用户登录情况(logged_in键存在会话中,并且为True)。向 SQL 语句中传递参数,需要在语句中使用问号?来代替参数,并把参数放在列表中进行传递。不要使用字符串格式化的方式直接把参数传入 SQL 语句中,这样可能会有潜在的 SQL 注入风险。

登录和注销:

这些函数是用于用户登录以及注销。登录时依据在配置中的值检查用户名和密码并且在会话中设置logged_in键值。如果用户成功登录,logged_in键值被设置成True,并跳转回show_entries页面。此外,会有消息闪现来提示用户登录成功。

如果发生错误,模板会通知,并提示重新登录。

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != app.config['USERNAME']:   # 如果用户名不符合
            error = 'Invalid username'
        elif request.form['password'] != app.config['PASSWORD']:   # 如果密码不符合
            error = 'Invalid password'
        else:
            session['logged_in'] = True   # 成功登录,在 session 中添加一个 logged_in 值为 True
            flash('You were logged in')   # 闪现一条消息
            return redirect(url_for('show_entries'))   # 重定向到首页
    return render_template('login.html', error=error)   # 如果没有成功登录则返回登录页面以及错误信息

 

 另一方面,注销函数从会话中移除了logged_in键值。这里我们使用一个大绝招:如果你使用字典的pop()方法并传入第二个参数(默认),这个方法会从字典中删除这个键,如果这个键不存在则什么都不做。这很有用,因为我们不需要检查用户是否已经登入。

@app.route('/logout')
def logout():
    session.pop('logged_in', None)   # 移除 logged_in 键
    flash('You were logged out')   # 闪现消息
    return redirect(url_for('show_entries'))   # 重定向到首页

模板:

现在我们应该开始编写模板。如果我们现在请求 URLs ,将会得到一个 Flask 无法找到模板的异常。模板使用 Jinja2 语言以及默认开启自动转义。这就意味着除非你使用Markup标记或在模板中使用|safe过滤器,否则 Jinja2 会确保特殊字符比如<>被转义成等价的XML实体。

我们使用模板继承使得在网站的所有页面中重用布局成为可能。

layout.html:

这个模板包含 HTML 主体结构,标题和一个登录链接(或者当用户已登录则提供注销)。如果有闪现信息的话它也将显示闪现信息。{% block body %} 块能够被子模板中的同样名字(body)的块替代。

session字典在模板中同样可用的,你能用它检查用户是否登录。注意在 Jinja 中你可以访问不存在的对象/字典属性或成员,如同下面的代码,即便 logged_in 键不存在,仍然可以正常工作。

simp_blog/templates 目录下新建 layout.html 文件并写入如下代码:

<!doctype html>
<title>Flaskr</title>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
  <h1>Flaskr</h1>
  <div class=metanav>
  {% if not session.logged_in %}
    <a href="{{ url_for('login') }}">log in</a>
  {% else %}
    <a href="{{ url_for('logout') }}">log out</a>
  {% endif %}
  </div>
  {% for message in get_flashed_messages() %}
    <div class=flash>{{ message }}</div>
  {% endfor %}
  {% block body %}{% endblock %}
</div>

show_entries.html:

这个模板继承了上面的layout.html模板用来显示信息。注意for遍历了所有我们用render_template()函数传入的信息。我们同样告诉表单提交到add_entry函数通过使用 HTTP 的POST方法

{% extends "layout.html" %}
{% block body %}
  {% if session.logged_in %}
    <form action="{{ url_for('add_entry') }}" method=post class=add-entry>
      <dl>
        <dt>Title:
        <dd><input type=text size=30 name=title>
        <dt>Text:
        <dd><textarea name=text rows=5 cols=40></textarea>
        <dd><input type=submit value=Share>
      </dl>
    </form>
  {% endif %}
  <ul class=entries>
  {% for entry in entries %}
    <li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}
  {% else %}
    <li><em>Unbelievable.  No entries here so far</em>
  {% endfor %}
  </ul>
{% endblock %}

login.html:

最后是登录模板,基本上只显示一个允许用户登录的表单。

{% extends "layout.html" %}
{% block body %}
  <h2>Login</h2>
  {% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %}
  <form action="{{ url_for('login') }}" method=post>
    <dl>
      <dt>Username:
      <dd><input type=text name=username>
      <dt>Password:
      <dd><input type=password name=password>
      <dd><input type=submit value=Login>
    </dl>
  </form>
{% endblock %}

添加样式:

现在其它一切都正常工作,是时候给应用添加些样式。

Code/simp_blog/static 目录下新建 style.css 样式文件并写入如下代码:

 

body            { font-family: sans-serif; background: #eee; }
a, h1, h2       { color: #377BA8; }
h1, h2          { font-family: 'Georgia', serif; margin: 0; }
h1              { border-bottom: 2px solid #eee; }
h2              { font-size: 1.2em; }

.page           { margin: 2em auto; width: 35em; border: 5px solid #ccc;
                  padding: 0.8em; background: white; }
.entries        { list-style: none; margin: 0; padding: 0; }
.entries li     { margin: 0.8em 1.2em; }
.entries li h2  { margin-left: -1em; }
.add-entry      { font-size: 0.9em; border-bottom: 1px solid #ccc; }
.add-entry dl   { font-weight: bold; }
.metanav        { text-align: right; font-size: 0.8em; padding: 0.3em;
                  margin-bottom: 1em; background: #fafafa; }
.flash          { background: #CEE5F5; padding: 0.5em;
                  border: 1px solid #AACBE2; }
.error          { background: #F0D6D6; padding: 0.5em; }

运行应用:

这样我们就完成了简单博客应用的代码编写,现在在终端执行如下命令运行程序:(在这之前注意要配置数据库,如果没有配置可以参考上一个实验的步骤)

python3 simp_blog.py
 * Serving Flask app "simp_blog" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 599-111-015

 

 

 

 

 

 点击首页的 log in 按钮,跳转到登录页面 http://127.0.0.1:5000/login,填入正确的用户名 admin 和密码 default,然后点击 Login 按钮进行表单提交,效果如下:

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值