flask系列讲座与2017年12月6日开始,每周一篇。第三篇其中讲述flask的配置方法。使用app.config.from_object()方法,似乎很神奇。如果明白背后逻辑,实际上很自然。涉及代码没有几行,背后逻辑涉及的代码也只有几行。
都说python简洁,这篇大概具有一定的典型性。简洁是指程序代码少,并不一定是含义少。
在microblog的文件夹中,涉及config的有config.py和子文件夹app中的__init__.py两个模块,config中的某些内容被flask使用 ,结构如下图。第一个microblog是文件夹,下有app子文件夹,以及config.py等文件,也是模块:
microblog\
app\
__init__.py
......
config.py
microblog.py
其中__init__.py代码
from flask import Flask from config import Config app = Flask(__name__) app.config.from_object(Config) from app import routes
config.py的代码
import os class Config(object): SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
在config.py中定义了Config的类,并含有类属性SECRET_KEY。
SECRET_KEY是flask要用的参数,在此也可以定义其它参数,只要参数名大写。
注意1:os.environ是一个存放环境变量的类,环境变量的值用get方法获取。os.environ.get('SECRET_KEY')获取名字为'SECRET_KEY'的值。注意SECRET_KEY与'SECRET_KEY'中的字符可以不一样,例如可以使用
os.environ.get('FORM_SECRET_KEY')
也是可以的,只要设置环境变量'FORM_SECRET_KEY'就可以了。
在flask的例子中,名字一样的不同变量比比皆是。
注意2:or是操作符吗?是的,or是操作符。当没有此名字的环境变量时,os.environ.get('SECRET_KEY')返回空字符''。对于字符操作,or操作符的含义是当or之前的运算结果不为空字符时,运算结果为or之前的运算结果,否则为or之后的结果。
注意3:对于os.environ,也可以看做字典变量,例如
>>>os.environ['SECRET_KEY']
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "d:\ProgramData\Anaconda3\lib\os.py", line 669, in __getitem__
raise KeyError(key) from None
KeyError: 'SECRET_KEY'
这里由于未定义此环境变量,所以产生KeyError,如果已定义则返回此环境变量的值。也可以使用字典的get方法:
>>>os.environ.get('SECRET_KEY','you-will-never-guess')
'you-will-never-guess'
__init__.py代码再看一次:
from flask import Flask from config import Config app = Flask(__name__) app.config.from_object(Config) from app import routes
这里小写c开始的两个config也是不同的变量,第一个config是模块名,对应文件config.py,第二个config是flask的属性,也是一个字典变量。
这里__name__为模块名,由
app = Flask(__name__)
是flask的实例,继承了config的属性,并且有from_object方法。
在说明from_object方法之前,先看一下builtins中的dir()的功能。
当dir()有类这样的object参数时,例如dir(Config),结果会这样:(这里由于__init__已执行,SECRET_KEY有值'you-will-never-guess')
>>>from microblog import app
>>>import config
>>>dir(Config)
['SECRET_KEY', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
这里列出的是字母顺序的所有可见的属性:
return an alphabetized list of names comprising (some of) the attributes of the given object, and of attributes reachable from it.现在可以看flask\from_object:
def from_object(self, obj): if isinstance(obj, string_types): obj = import_string(obj) for key in dir(obj): if key.isupper(): self[key] = getattr(obj, key)
只要是object,例如类,就不会判为
isinstance(obj, string_types)
并且此类的可见的大写的属性(isupper()),添加到字典中!其中getattr是取此属性的值。
执行文中的验证为:
>>>from microblog import app>>>app.config['SECRET_KEY']
'you-will-never-guess'
附:
microblog的程序,只有一行。
from app import app
第一个app是pakeage,即app文件夹所包含的pakeage,后一个app是flask的实例,在__init__中的那个app:
app = Flask(__name__)第一篇的URL如下,每篇前面都有所有目录
https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world