我的个人博客搭建日志------Flask篇之官方教程

引言

之前跟着教程用Django写过一个博客,不过都是看着抄,能运行就下一章,没学到啥。现在决定重新用flask写个,然后每次看完都记录学到什么,慢可以,但不能写出了个博客问你啥你都不知道

官方文档的入门指南

Step 0:创建文件

教你怎么创建文件,我直接用pycharm自动生成了就直接跳过

Step 1:数据库架构

创建个数据库

drop table if exists entries;
create table entries (
  id integer primary key autoincrement,
  title text not null,
  'text' text not null
);

其他都懂,为啥text要有单引号?

Step 2:应用程序设置代码

app = Flask(__name__) # create the application instance :)
app.config.from_object(__name__) # load config from this file , flaskr.py

# Load default config and override config from an environment variable
app.config.update(dict(
    DATABASE=os.path.join(app.root_path, 'flaskr.db'),
    SECRET_KEY='development key',
    USERNAME='admin',
    PASSWORD='default'
))
app.config.from_envvar('FLASKR_SETTINGS', silent=True)

整个设置程序,指南里说最好的办法是把这些配置信息一起写到一个.ini或者.py的文件里
Flask()是创建一个应用程序
app.config.from_object设置从哪里加载配置文件
app.config.update是设置配置信息,Flask会找到配置信息里面大写的参数进行初始化,其中

  • app.root_pathos.path是为了适应不同的操作系统的文件系统
  • secret_key是用来保护用户端的session安全的

app.config.from_envvar是表示用环境变量来设置需要加载的配置文件,因为开发中和上线时需要的配置文件是不一样的(像是DEBUG)所以可以通过在shell脚本中设置要配置的文件,在运行Flask,后面的silent的意思是如果没有给环境变量赋值不报错

Step 3:像安装包一样的安装flaskr

里面讲了为了以后可以用pip install ***的方式来安装程序,所以参照python打包指南里的方式来设计程序目录。

/flaskr
    /flaskr
        __init__.py
        /static
        /templates
        flaskr.py
        schema.sql
    setup.py
    MANIFEST.in

里面新增了setup.py__init__.pyMANIFEST.in
setup.py

from setuptools import setup

setup(
    name='flaskr',
    packages=['flaskr'],
    include_package_data=True,
    install_requires=[
        'flask',
    ],
)

MANIFEST.in
指定那些文件需要被包含

graft flaskr/templates
graft flaskr/static
include flaskr/schema.sql

文档里说明的命令代表的内容

命令 内容
include pat1 pat2 ... include all files matching any of the listed patterns
exclude pat1 pat2 ... exclude all files matching any of the listed patterns
recursive-include dir pat1 pat2 ... include all files under dir matching any of the listed patterns
recursive-exclude dir pat1 pat2 ... exclude all files under dir matching any of the listed patterns
global-include pat1 pat2 ... include all files anywhere in the source tree matching — & any of the listed patterns
global-exclude pat1 pat2 ... exclude all files anywhere in the source tree matching — & any of the listed patterns
prune dir exclude all files under dir
graft dir include all files under dir

init.py

from .flaskr import app

运行方式

export FLASK_APP=flaskr
export FLASK_DEBUG=true
flask run

windows下用set来代替export

Step 4:数据库连接

里面提到了俩个上下文(context),一个application上下文和一个request上下文,我感觉context翻译成语境好点,上下文看的一脸懵逼,对应这俩上下文有俩个关键字requestg来分别代表request和application
然后是创建数据库连接的代码

def get_db():
    """Opens a new database connection if there is none yet for the
    current application context.
    """
    if not hasattr(g, 'sqlite_db'):
        g.sqlite_db = connect_db()
    return g.sqlite_db

关闭连接

@app.teardown_appcontext
def close_db(error):
    """Closes the database again at the end of the request."""
    if hasattr(g, 'sqlite_db'):
        g.sqlite_db.close()

teardown_appcontext()会在每次application 上下文摧毁时调用
application上下文是先于request上下文创建时创建,后于request上下文结束时结束

Step 5:创建数据库

通过在flask命令行里加入一个钩子方法用来初始化数据库

def init_db():
    db = get_db()
    with app.open_resource('schema.sql', mode='r') as f:
        db.cursor().executescript(f.read())
    db.commit()

@app.cli.command('initdb')
def initdb_command():
    """Initializes the database."""
    init_db()
    print('Initialized the database.')

app.cli.command()装饰器会在flask命令行里注册一个新的initdb命令,当执行这个命令后flask会自动创建一个application上下文,当执行完方法里的代码后再自己摧毁和释放数据库连接
open_resource()是一个方便开发者的方法,可以直接定位项目中的资源文件夹位置
现在开始执行初始化

set FLASK_APP=flaskr  //这里文档里没写所以运行时会提示没有该命令
flask initdb
Initialized the database.

Step 6:视图方法

主页视图

@app.route('/')
def show_entries():
    db = get_db()
    cur = db.execute('select title, text from entries order by id desc')
    entries = cur.fetchall()
    return render_template('show_entries.html', entries=entries)

添加新实体

@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)
    db = get_db()
    db.execute('insert into entries (title, text) values (?, ?)',
                 [request.form['title'], request.form['text']])
    db.commit()
    flash('New entry was successfully posted')
    return redirect(url_for('show_entries'))

abort()发送错误代码给WSGI应用

flask.flash(message, category=’message’)
Flashes a message to the next request. In order to remove the flashed message from the session and to display it to the user, the template has to call

不太懂,说是闪烁消息,感觉想Android里面的toast,但是感觉又是Android里面的广播
例子的实现方式是想日志一样,就是为了友好的人机交互
文档里写会发送信息到下个请求和重定向到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)

登出

@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))

Step 7:模板

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

{% 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 %}

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; }

在这停顿

大概了解到了整个flask的基本运行方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 22年12月更新:个人网站关停,如果仍旧对旧教程有兴趣参考 Github 的markdown内容[https://...
    tangyefei阅读 35,217评论 22 257
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,881评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,116评论 25 708
  • [TOC]一直想做源码阅读这件事,总感觉难度太高时间太少,可望不可见。最近正好时间充裕,决定试试做一下,并记录一下...
    何柯君阅读 7,219评论 3 98
  • 人闲桂花落, 夜静春山空。 月出惊山鸟, 时鸣春涧中。 今天给孩子们讲了这首诗,人闲,夜静,春山空,一片幽...
    嘎鱼嘎鱼阅读 425评论 0 1