python-flask笔记(六)

此章和教程出入不大,可直接看原教程

  • 之前写的代码耦合太重,python也可以像js模块化一样模块化程序结构

模块化

  • 使用 蓝图(蓝本),我们之前的程序都有一个Flask的实例
app = Flask(__name__)
  • 这个app变量可以定义路由,蓝图就是可以将路由分门别类,然后在组合在一起
  • 需要重新设置一下目录结构:
.
├── app
│   ├── admin
│   │   ├── errors.py
│   │   ├── forms.py
│   │   ├── __init__.py
│   │   └── views.py
│   ├── __init__.py
│   ├── main
│   │   ├── forms.py
│   │   ├── __init__.py
│   │   └── views.py
│   ├── models.py
│   ├── static
│   └── templates
│       ├── 404.html
│       ├── 500.html
│       ├── admin
│       │   ├── login.html
│       │   └── register.html
│       ├── base.html
│       ├── index.html
│       └── user.html
├── config.py
├── manage.py
  • Flask 程序一般都保存在名为app的包中.
  • config.py 保存着配置
  • manage.py 用于启动项目

说明一下python 的包(package),从目录结构上看,python的package有两部分组成: 文件夹和init.py 文件. 正是因为init.py 的存在 python编译器才会把那个文件夹当作是一个python的包来看待. 而那个 init.py 的效果就是, 能够有一个与包名字相同的文件. 什么意思呢?
比如 我们有一个名字为 main 的包, 那么

from main import *

这行代码中,从main包中import所有的东西,你想啊,main是个包,import进来是啥??? 其实阿,import进来的是init.py中的内容.

  • 把原先那个blog.py中的东西复制一下就好了:
    • config.py:
import os

basedir = os.path.abspath(os.path.dirname(__file__))


class Config:
    SECRET_KEY = 'a string'
    # 数据库配置
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
    SQLALCHEMY_COMMIT_TEARDOWN = True
    SQLALCHEMY_TRACK_MODIFICATIONS = False

    @staticmethod
    def init_app(app):
        pass

仿照狗书,创建一个程序工厂函数. 设计模式中有一个模式叫做:工厂模式,比如你需要一个东西,但这个东西你需要配置很多,这样你就可以用到工厂模式,在把配置(比如汽车厂,把各个零件组装起来)的活交给工厂,那么工厂出来的产品就是好的产品.这样可以降低程序的耦合度,怎么理解呢,如果这个产品是坏的,那么你也不需要到处去程序的代码,只需要去那个工厂的程序中去寻找bug就好了

程序工厂函数:

说一下工厂函数,我们之前单个文件开发程序很方便,但却有个很大的缺点,因为程序在全局作用中创建,所以无法动态修改配置.运行脚本时,实例已经创建,再修改配置为时已晚,解决问题的方法就是延迟创建程序实例,把创建过程移到可显式调用的工厂函数中.

  • app/init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

from config import Config

db = SQLAlchemy()


def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    Config.init_app(app)

    db.init_app(app)

    return app

这段代码,我们的db实例,先于app创建,app的创建只能调用了create_app()函数之后才创建.

蓝图:

Flask 中的蓝图为这些情况设计:

  • 把一个应用分解为一个蓝图的集合。这对大型应用是理想的。一个项目可以实例化一个应用对象,初始化几个扩展,并注册一集合的蓝图。
  • 以 URL 前缀和/或子域名,在应用上注册一个蓝图。 URL 前缀/子域名中的参数即成为这个蓝图下的所有视图函数的共同的视图参数(默认情况下)。
  • 在一个应用中用不同的 URL 规则多次注册一个蓝图。
  • 通过蓝图提供模板过滤器、静态文件、模板和其它功能。一个蓝图不一定要实现应用或者视图函数。
  • 初始化一个 Flask 扩展时,在这些情况中注册一个蓝图。

蓝图问题,最后总结:

  • 在蓝本中定义的路由处于休眠状态,直到蓝本注册到程序上后,路由才真正成为程序的一部分

创建蓝本:

  • app/main/init
from flask import Blueprint

main = Blueprint('main', __name__)

from . import views, errors

蓝图是通过实例化Blueprint类对象来创建的。这个类的构造函数接收两个参数:蓝图名和蓝图所在的模块或包的位置。与应用程序一样,在大多数情况下,对于第二个参数值使用Python的name变量即可。

应用程序的路由都保存在app/main/views.py模块内部,而错误处理程序则保存在app/main/errors.py中。导入这些模块可以使路由、错误处理与蓝图相关联。重要的是要注意,在app/init.py脚本的底部导入模块要避免循环依赖,因为view.py和errors.py都需要导入main蓝图

注册蓝图:

  • app/init.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

from config import Config

db = SQLAlchemy()


def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    Config.init_app(app)

    db.init_app(app)

    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)
    #通过register_blueprint方法将蓝图注册进来
    
    return app
  • app/main/errors.py:
from flask import render_template

from . import main


@main.app_errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


@main.app_errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500
  • app/main/views.py:
from flask import render_template
from flask import session
from flask import redirect
from flask import url_for
from flask import request

from . import main
from ..models import User
from .. import db


@main.route('/', methods=['GET', 'POST'])
def index():
    if 'name' in request.args:
        name = request.args['name']
        return render_template('user.html', username=name)
    else:
        return render_template('index.html')


@main.route('/register', methods=['POST'])
def register():
    username = request.form['username']
    password = request.form['password']

    if username:
        user = User.query.filter_by(name=username)
        if user is None:
            ##添加进数据库
            user = User(name=username)
            ##如果没有app.config['SQLALCHEMY_COMMIT_TEARDOWN'] = True
            ##这句后面还要加上db.session.commit()才会提交到数据库
            db.session.add(user)
            session['known'] = False
        else:
            session['known'] = True
        session['name'] = username

    name=session.get('name')
    return '你的用户名是 %s' % name
  • manage.py:
from flask_script import Manager

from app import create_app, db

app = create_app()
manager = Manager(app)

if __name__ == '__main__':
    manager.run()
  • app/models.py:
from . import db


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    # 如果你学过数据库的话就知道我们一般通过id来作为主键,来找到对应的信息的,通过id来实现唯一性
    name = db.Column(db.String(64), unique=True)

    def __repr__(self):
        return 'users表: id为:{}, name为:{}'.format(self.id, self.name)
  • 在终端输入:
python manage.py shell
>>> from manage import *
>>> db
<SQLAlchemy engine=sqlite:////home/me/PycharmProjects/blog/data.sqlite>
>>> db.drop_all()
>>> db.create_all()
>>> exit()
  • 这里把表重新创建了一下,因为表已经移动位置了.
    然后:
python manage.py runserver

然后就可以正常运行了

运行的时候注意有没有更改端口,改了的话html文件里的请求接口也记得改一下
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容

  • flask是python的一个web应用框架,django很多人听过,flask比较少见,连创始人一开始写出来只是...
    思而忧阅读 2,942评论 0 5
  • 22年12月更新:个人网站关停,如果仍旧对旧教程有兴趣参考 Github 的markdown内容[https://...
    tangyefei阅读 35,181评论 22 257
  • 第七章 大型程序架构 虽然在一个脚本里完成一个web应用很便利,但是这也意味着它很难扩展。当程序不断增长,越来越复...
    易木成华阅读 914评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,654评论 18 139
  • 和身边的朋友一起进步才是真正的进步。这样自然而然会留住很多朋友。这样你们在一起才不会荒废时间,对于一份工作着重要看...
    李阳_98d1阅读 137评论 1 0