zoukankan      html  css  js  c++  java
  • 一个简单地flask应用

    /flaskr

      /static

      /template

    用户可以通过HTTP访问static文件夹中的文件,这里也是css和javascript文件存放位置,flask将会在templates文件夹中寻找Jinja2模板,

    要支持SQLite,将下列文件放入schema.sql

    drop table if exists entries;

    create table entries(

    id interger primary key autoincrement,

    title string not null,

    text string not null);

    在flaskr.py中,

    import sqlite3

    from flask import Flask,request,session,g,redirect,url_for,abort,render_template,flash

    #configuration

    DATABASE = '/tmp/flaskr.db'

    DEBUG = True

    SECRET_KEY = 'development key'

    USERNAME = 'admin'

    PASSWORD = 'default'

    创建应用,在同一文件中配置初始化:

    app = Flask(__name__)

    app.config.from_object(__name__)

    from_object()将会寻找给定的对象(如果他是一个字符串),搜寻里面定义的全部大写的变量,

    从配置文件加载配置是from_envvar()所做的,用于替换from_object()

    app.config.from_envvar('FLASKr_SETTINGS',silent=True)

    这种设置方法我们可以设置一个名为FLASKR_SETTINGS环境变量来设定一个配置文件载入之后是否覆盖默认值,静默开关告诉FLask不去关心这个环境变量键值是否存在

    secret_key是需要为了保持客户端的会话安全,

    添加一个轻松连接到指定数据库的方法,这个方法用于请求时打开一个连接.

    def connect_db():

      return sqlite3.connect(app.config['DATABASE'])

    如果想要把那个文件当做独立应用来运行,只需要加上:

    if  __name__ == '__main__':

    app.run()

    顺利开始运行这个应用.使用如下命令:

    python flaskr.py 

    创建数据库

    Flaskr是一个使用关系型数据库的应用程序,这样的系统需要一个模式告诉他们如何存储信息,因此在首次启动服务器之前,创建数据库模式,可以通过管道把schema.sql作为sqlite3命令的输入来创建这个模式,命令如下:

    sqlite3 / tmp/flaskr.db <schema.sql>

    这种方法的缺点是需要安装sqlite3命令,而并不是每个系统都有安装,必须提供数据库的路径,否则将报错,

    可以添加一个函数来初始化数据库

    首先从contextlib包中导入contextlib.closing()函数,并且在flaskr.py文件中添加如下的内容;

    from contextlib import closing

    接着可以创建一个称为init_db函数,该函数用来初始化数据库,我们可以使用之前定义的connect_db函数,添加这样的函数:

    def init_db():

      with closing(connect_db()) as db:

        with app.open_resource('schema.sql') as f:

          db.cursor().executescript(f.read())

        db.commit()

    closing()助手函数允许我们在with块中保持数据库连接可用,应用对象的open_resource()方法在其方框外也支持这个功能,因此可以在with块中直接使用,这个函数从资源位置(你的flaskr文件夹)中打开一个文件,并且允许读取

    当我们连接到数据库时会得到一个数据库连接对象,这个对象提供给我们一个数据库指针,

    请求数据库连接:

    在函数中需要数据库连接,在请求之前初始化他们,请求结束后自动关闭

    Flask允许我们使用before_request(),after_request()和teardown_request()装饰器来实现这个功能:

    @app.before_request

    def before_request():

    g.db = connect_db()

    @app.teardown_request

    def teardown_request(exception):

    g.db.close()

    使用before_request()装饰器的函数会在请求之前被调用而且不带参数.使用after_request()装饰器的函数会在请求之后被调用且传入将要发给客户端的响应.他们必须返回那个响应对象或是不同的响应对象,但当异常被抛出时,他们不一定会被执行,并不允许修改请求,返回的值会被忽略.如果在请求已经被处理的时候抛出异常,他会被传递到每个函数,否则会传入一个None

    我们把当前的数据库连接保存在Flask提供的g特殊对象中,这个对象只能保存一次请求的信息,并且在每个函数里都可用,不要用其他对象来保存信息,因为在多线程环境下将不再可行,特殊的对象g在后台有一些神奇的机制来保证他在做正确的事情.

    视图函数

    显示条目:

    这个视图显示所有存储在数据库的条目,他监听着应用的根地址以及会从数据库中查询标题和内容,id值最大的条目将在前面,从游标返回行是按select语句中声明的列组织的元组,视图函数将会把条目作为字典传入show_entries.html模板及返回渲染结果

    @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',enries=entries)

    添加新条目

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

    @app.route('/add',methods=['POS'])

    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 successful posted')

    return redirect (url_for('show-entries'))

    登录和注销

    这些函数是用于用户登录以及注销,依据在配置中的值登录时检查用户名和密码并且在会话中设置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

        flash('You were logged in')

        return redirect(url_for('show_entries'))

      return render_template('login.html',error=error)

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

    @aa.route('/lgout')

    def logout():

      session.pop('logged_in',None)

      flash('You were logged out')

      return redirect(url_for('show_entries'))

    模板

    模板使用Jinja2语言以及默认开启自动转义,意味着除非使用Markup标记或在模板中使用|safe过滤器,否则jinja2会确保特殊字符比如<或>被转义成等价的XML实体,session字典在模板中同样可用的,注意在Jinja中你可以访问不存在的对象/字典属性或成员,及时键不存在仍然可以正常工作

    <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 %}
  • 相关阅读:
    如何自定义一个通信协议
    c++ 如何编写接口类(interface)
    QT国际化(中英转换)
    QT中文乱码与国际化支持
    frp官方中文文档
    K3 LEDE固件更改FRP客户端版本
    Linux下的tar压缩解压缩命令详解
    QT入门系列(3):控制台输出QString
    Delphi、Lazarus保留字、关键字详解
    使用TortoiseSVN的客户端钩子脚本触发Jenkins构建
  • 原文地址:https://www.cnblogs.com/suncunxu/p/11281817.html
Copyright © 2011-2022 走看看