用python+flask搭建一个博客需要学习哪些知识

你正在使用的浏览器版本过低,将不能正常浏览和使用知乎。flask学习笔记 -
- ITeye技术网站
博客分类:
Micro means Flask aims to keep the core simple but extensible.
Flask won't make any decisions for you(database, template, form validation, authorization, uploading file, etc), everything is up to you. so flask can be anything you need and nothing you don't.
conventions:
static files and templates are stored in application's subdirectories within the application's Python source code tree, named static and templates, and this can be changed if you want to.
class Flask is designed to inherit, so you can customize your application behavior.
Thread-locals in Flask:
One of the design decisions in Flask was that simple ta they should not take a lot of code and yet they should not limit you. Because of that, Flask has few design choices that some people might find surprising or unorthodox. For ex- ample, Flask uses thread-local objects internally so that you don’t have to pass objects around from function to function within a request in order to stay threadsafe. This approach is convenient, but requires a valid request context for dependency injection or when attempting to reuse code which uses a value pegged to the request. The Flask project is honest about thread-locals, does not hide them, and calls out in the code and documentation where they are used.
Always build web application with CAUTION:
Flask and Jinja2 protect you from XSS
Installation:
Flask depends on Werkzeug and Jinja2. Werkzeug is a toolkit fo WSGI, the standard Python interface between web applications and variety of servers for both development and deployment.
virtualenv:
a really nice tool.
in virtualenv mode:
&&& pip install Flask
or system-wide installation:
&&& sudo pip install Flask
Quick start:
hello-word:
from flask import Flask&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
##__name__ is needed for Flask to know where is current module or package is,
##and where to find static and templates.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
app = Flask(__name__)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
@app.route("/")&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
def hello_world():&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& return "Hello world"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
if __name__ == "__main__":&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& app.run()
now access 192.168.1.1:5000 you will get "Hello world". but the application is only accessible in your computer, use app.run(host=0.0.0.0) to tell the operation system to listen on all public IPs.
Debug Mode:
debug mode let Flask restart the web application automatically when detects source code changes.
two ways to implement:
1. app.debug = True
2. app.run(debug=True)
Routing: to build beautiful URLs.
@app.route("/")
@app.route("/projects/"): access /projects will to /projects/, projects looks like a directory
@app.route("/about"): access /about/ will 404, about behaves like a file
@app.route("/post/&post_id&/"): access post_id as dynamic argument
@app.route("/user/&int:user_id&/"): receive int user_id, and user_id as the function argument, int is converter
@app.route("/user/&path:url&"): url can be abc, or ab/c, path converter accepts slashes.
existing converters:
1. int:
2. float:
3. path: like the default converter but accepts slashes.
URL Building:
url_for方法能输出指定controller方法对应的url,为什么不在template里直接使用硬编码的url而要使用url_for方法呢?
1. url_for比硬编码的url更具有描述性(更好记)(可我没发现),而且,当需要修改一个url时,只需在controller定义接口的地方一处修改即可
2. url_for会为你处理转义
3. 如果你的应用程序是某个大应用的一个模块,url_for会自动为你处理,比如豆瓣小组,单独运行会是"/", 但如果放在豆瓣这个大的application下,url_for会生成"/group/"
代码:
with app.test_request_context():&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& print url_for('projects')&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& print url_for('url', url='ab/c')&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& print url_for('url', url='ab/robert json')
输出:
/projects/
/people/ab/c
/people/ab/robert%20json
HTTP Methods:
@app.route("/login", methods=["GET", "POST"])&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
def login():&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& if request.method=="GET":&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& #show_login_form()&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& pass&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& elif request.method=="POST":&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& #check_login_form()&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& pass
methods:
GET: get information from body
HEAD: trigger get action, but only interested in header
POST: put data in server(and server trigger store action only once)
PUT: similar with POST, but can trigger POST many times, so it' ok even the transmission breaks.
DELETE: delete data
OPTIONS: this method is implemented automatically by Flask, for the browser to figure out which method(s) does the url supports.
Static File:
create a directory named static in your package or next to your modul, to generate urls for static files, use url_for:
url_for("static", filename="main.css")
the file has to be stored in fs as static/main.css
Rendering Templates:
generating HTML from python is not funny, but cumbersome because you have to make sure your application's secure.
use render_template and pass the template name and the context variables:
@app.route("/hello/&user_name&")&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
def hello(user_name):&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& return render_template('hello.html', user_name=user_name)
templates/hello.html:
&!doctype html&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
hello, {{user_name}}
inside the template you can access the request/session/g object as well as get_flashed_messages() function.
use template, use template inheritance.
Accessing request data:
in Flask you can access the request data with global request object.
how's that possible?
proxy!
when the web server receives a request, it spawn a new thread,& when flask begin to deal with the request, it binds the current application and WSGI environments to that context(thread).
with flask, even in unittest it's easy for you to create a request:
with app.test_context_request('/hello', method='POST'):
&&& assert request.path == '/hello'
&&& assert request.method == 'POST'
the request object:
to get form data:
request.form['username']
but if the key doesn't exist in the form, Flask wil raise KeyError, Flask defaults it to 404.
to access parameters in url?key=value form, use request.args.get('key', default_value)
file uploading:
first set enctype="multipart/form-data"
use request.files to access the files, and request.files['form_name'] to access the specified file.
the file has filename attribute, but it can be forged, so use werkzeug.secure_filename(filename)
@app.route('/upload', methods=["GET", "POST"])&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
def upload_resume():&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& message = ''&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& if request.method=="POST":&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& file1 = request.files['file1']&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& if not file1:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&& message = 'file not found'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& else:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&& file1.save("/Users/liaofeng/python/flask/uploads/" +&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& secure_filename(file1.filename))&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&& message = 'file saved'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& return render_template('upload.html', message=message)
&!doctype html&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
{% if message %}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& {{message}}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
{% endif %}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&form action="/upload" method="POST" enctype="multipart/form-data"&&&&&&&&&&&&&
&&& select file: &input type="file" name="file1" /&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& &input type="submit" value="submit"/&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
cookie:
access cookie: request.cookies, it's a dictionary
set cookie: response.set_cookie('name', 'value')
how to get response object:
1. if a controller method returns a string, Flask will automatically creates the response object.
2. use flask.make_response(response_string) method to explicitly create a response object.
but sometimes you might want to set cookie at the point response object doesn't exist, in this condition, use Deferred Request Callbacks pattern.
Redirect:
from flask import redirect
return redirect(url_for('login'))
abort a request earlier with a error code:
from flask import abort
abort(404) # notice: no return exists
this_will_never_execute()
or use errorhandle:
@app.errorhandle(404)
def page_not_found(error):
&&& return render_template('page_not_found_error.html'), 400
404 is the http response code, it defaults to 200
Response:
with the string returned from a controller method, it will be used as the response body, with http response code 200 and text/html mimetype.
if the return is a tuple, show be in form (response_body, code, headers)
Sessions:
store some information for some use from one request to the next.
session is implemented on top of cookie and set the cookie cryptographically,
is means use can look the cookie content but can't modify it unless he knows the secret key for signing.
from flask import Flask, request, render_template, session, redirect, url_for&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
app = Flask(__name__)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
app.debug = True&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
app.secret_key = '\xbbM\xfe\t@q\x11\xeb\xf2Y\x089\x8f\x07\xa6\x82q\x1e\x85RD\x92 \x93'
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
@app.route('/')&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
def index():&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& return "user in session: %s" % session.get('username', 'none')&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
@app.route('/login', methods=["GET", "POST"])&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
def login():&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& if 'username' in session:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& return redirect(url_for('index'))&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& if request.method=="GET":&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& return render_template("login.html")&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& else:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& session['username'] = request.form['username']&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& return redirect(url_for('index'))
@app.route('/logout')&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
def logout():&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& if 'username' in session:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&& session.pop('username')&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& return redirect(url_for('login'))&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
if __name__=='__main__':&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&& app.run()
how to generate secret key:
import os
os.urandom(24)
note: make sure the cookie and session below the browser's maximum capacity.
Message flashing:
Logging:
app.logger.debug()
app.logger.warning()
app.logger.error()
that's all, thank you.
liaofeng_xiao
浏览: 87362 次
来自: 北京
if(&classname& in x.p ...
测试代码无法运行,死循环了:enhancer.setCallb ...
谢谢,在这里找到了我想要的答案。
刚开始我不知道是如何加载ap ...
很有帮助 我可以转走吗?谢谢
写的好!喜爱原创! 支持带你入门python(基于flask的web应用)的学习- Python教程-PHP中文网QQ群微信公众号带你入门python(基于flask的web应用)的学习Flask是一个非常优秀的web框架,它最大的特点就是保持一个简单而易于扩展的小核心,其他的都有用户自己掌握,并且方便替换,甚至,你可以在社区看到众多开源的,可直接用于生产环境下的扩展。到目前为止,我相信关于他的介绍以及非常的多,就算cnblog中,随便一搜也会有很多内容,但还是抛砖引玉,就当是一个自我的总结部署环境安装python首先,当然是安装python环境,去官网来下载最新的环境(我选择最新的3.6版本)然后一路下一步即可,注意记录或选择一下安装路径。环境变量接下来配置环境变量与java几乎一样,path后;.;输入python的安装路径,然后再次;,;输入python目录下的Scripts文件夹,已使用py自带的一些工具(如pip)安装flask配置完成pip后,安装flask就很简单了,输入cmd进入控制台,然后输入如下命令即可:pip3.6 install flask开发工具工欲善其事必先利其器,开发工具的选择很重要,我选择的是pycharm,也可从官网下载,以及请大家使ji用huo正fang版shi开始开发首先,打开pycharm,创建一个Pure Python项目:项目创建好之后,有的也仅仅是一个空项目,还有创建一个py文件已进行开发,在项目文件夹下右键new--&python file 然后取一个名字,我取得名字为default,将在目录文件夹下创建default.py文件。flask初探在此文件上输入代码(假设安装flask已经成功):from flask import Flask #导入Flask类
app=Flask(__name__) #创建Flask类的一个实例
if __name__=='__main__': #Python入口程序
app.run(debug=True) #使其运行于本地服务器上这是可将cmd控制台的目录切换至项目目录,输入命令:python default.py导入Flask类后,运行脚本时会自动创建WSGI程序如图显示即为正确:根据提示,此时在浏览器中输入flask的默认地址,显示如下:因为现在还没有任何页面,所有访问任何地址均为404说明debug=true代表运行在调试模式,调试模式绝对不能用于生产环境!!!路由下面为此应用创建一个默认路由,flask使用装饰器为路由配置:@app.route(&/&)
def index():
return &&h1&hello world&/h1&&此时访问,页面如下:输出return的内容,而此时的控制台显示:状态码为200,不再为404这里的装饰器暂时可以理解为java中的注解,以后再详细讨论,同时这种路由的使用方式也可以暂时理解为j2ee中servlet的注解式路由方式。带参路由同时flask也支持带参路由:@app.route(&/user/&name&&)
def user(name):
return &&h1&hell %s&/h1&&%name在浏览器中输入:<span style="color: #7.0.0.1:5000/user/niufen此时输入为:关于路由暂时先说这么多,然后进入cmd控制台,ctrl+c退出服务器,输入python,进入python命令行界面,此时可以执行各种py语句然后在此界面导入default.py对象下的app对象:from default import app然后回车,此时可以在命令行中使用app对象,输入:app.url_map我的显示如下:可以看到,使用一个map存储了此对象下的所有路由,并从内容可以看到 全是get方式,注意其中的static,是存放的静态文件,如图片,顺便提一下,这也体现了flask的一个特点,即它有众多的配置选项,但基本上都在初始状态下有个明确的默认值,比如模板在templates中,图片在static中,虽然这个配置可以修改,但不建议这么做,尤其是刚开始的时候。from default import app这行代码代表了从default对象中导入app,并在之下可以直接使用app,同样的还有之前的代码 from flask import Flaskpython中有两种导入方式,import直接导入和from ... import导入,具体区别可查看py基本语法如果想让路由为post方式,也很简单:@app.route(&/user&,methods=[&POST&])
def user():
name=request.args.get(&name&)
return &&h1&hell %s&/h1&&%name即可请求上下文flask还有请求上下文对象,即request,如:from flask import request #页头 导入request对象
@app.route(/req_test)
def req_test():
for key,value in request.args.items():
val+=& %s = %s &br&&%(key,value)
在控制台输入exit()后,继续输入python default.py进入服务器此时在浏览器中输入url:127.0.0.1:5000/req_test?age=5&name=abc此时浏览器中显示为:测试代码2(假设已导入request对象):@app.route(/req_test)
def req_test():
for key,value in request.headers.items():
val+=& %s = %s &br&&%(key,value)
浏览器显示为:flask自带系统上下文共计四个:current_app 约等于application g 一个用于临时存储的对象 约等于viewbagrequest 与servlet或asp.net中含义大体相同session 与servlet或asp.net中含义大体相同响应flask响应可以使用make_response对象,用法与java servlet中的用法类似:from flask import make_response #页头,导入make_response对象
@app.route(&/res_test&)
def res_test():
response=make_response(&&h1&hello world&/h1&)
response.set_cookie(&name&,&niufennan&)
此代码的内容为在响应的时候设置cookie在浏览器中输入地址:127.0.0.1:5000/res_test在页面中显示为黑体hello world,但是可以查看浏览器,发现响应内容已经存入浏览器的cookie中 如图:其他常用功能:跳转在web开发中,经常会遇到直接跳转的情况,flask中也提供了redirect方法来实现:from flask import redirect # 页头,导入redirect对象
@app.route(&/&)
def index():
return redirect(&/&)此时访问将直接跳转至百度其他常用功能:响应码普通响应码可直接在return的返回字符串后使用,如:@app.route(&/&)
def index():
return &&h1&hello world&/h1&&,400访问结果如下:可以看到,虽然此时页面显示内容不变,但是响应码为400错误码flask也提供了一个专有的函数:from flask import abort #导入abort对象
@app.route(&#39;/user/&name&&#39;)
def user(name):
if name ==&#39;test&#39;:
abort(500)
return &&h1&hello %s!&/h1&&%name此代码的功能是当name的值为test是,返回错误码为500,注意此时页面不会显示内容,因为此时程序不由代码控制,而将控制权交给了系统。至此,flask基础知识已经讲完,现在已经可以做一些简单的程序,但是肯定不会如此的做,就像只用servlet,不用jsp页面或其他模板也可以做出很绚丽的系统,但大部分还是需要jsp页面或其他模板页作为支撑,下一章将说明在系统中如何使用jinja2模板引擎和wtf表单插件。以上就是带你入门python(基于flask的web应用)的学习的详细内容,更多请关注php中文网其它相关文章!972点赞收藏分享:&猜你喜欢12345678910
PHP中文网:独家原创,永久免费的在线,php技术学习阵地!Copyright
All Rights Reserved | 皖B2-QQ群:关注微信公众号[python] Flask框架的学习指南之制作简单blog系统 | IT知识库
-& 正文阅读
[python]Flask框架的学习指南之制作简单blog系统
Flask框架的学习指南之制作简单blog系统
本文是Flask框架的学习指南系列文章的第二篇主要给大家讲述制作一个简单的小项目blog系统的过程,有需要的小伙伴可以参考下之前写了一篇flask开发环境搭建,今天继续,进行一个实战小项目-blog系统。blog系统很简单,只有一个页面,然后麻雀虽小五脏俱全。这里目的不是为了做项目而做项目,这篇文章本意是通过这次练习传达以下几个知识点:1、从全局上了解flask项目的目录结构2、flask项目的运行机制3、flask框架实现MVC架构4、flask-sqlalchemy 操作mysql数据库一、新建项目:blog系统在pycharm中,新建flask项目,如下图:
完成后的目录结构是这样的:非常简单,一个static文件夹,一个templates文件夹,一个py文件
以上的目录结构是flask初始时的结构,这个只能应对很小的项目,对于大型复杂的项目,我们需要引入包的管理,MVC架构设计。二、目录结构重构,引入包管理针对上面的结构,在最上层blog3目录下,&& 1、新建一个runserver.py文件,作为项目统一入口文件&& 2、新建blog文件夹,把已存在的static,templates,blog3.py移到blog文件夹下,然后分别建controller、model文件夹。把blog3.py改名为__init__.py,现在目录如下所示:
这样就相当于一个大工程结构了:1)最上层blog2目录是项目名称,一个项目下可以包括多个模块,也就是应用,每个应用下有自己的配置文件,初始化文件,MVC架构。2)runserver.py:与应用模块平级,作为项目启动文件3)第二级blog2目录:模块名称&&&&&& controller目录:MVC中的C,主要存放视图函数&&&&&& model目录:MVC中的M,主要存放实体类文件,映射数据库中表&&&&&& templates:MVC中的V,存放html文件&&&&&& static:静态文件,主要存放css,js等文件&&&&&& __init__.py:模块初始化文件,Flask 程序对象的创建必须在 __init__.py 文件里完成, 然后我们就可以安全的导入引用每个包。&&&&&& setting.py:配置文件,数据库用户名密码等等三、开发代码1、先把项目运行起来:1) 编写__init__.py文件,创建项目对象,代码如下:
# -*- coding: utf-8 -*-
from flask import Flask
#创建项目对象
app = Flask(__name__)
2) 在runserver.py文件中添加如下代码:
from blog3 import app
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True)
3)运行runserver.py文件:
然后在浏览器中输入:http://127.0.0.1:5000/,会显示helloworld字样
到这里,项目雏形就可以正常运行了,下面的事情就简单了,添加内容,让项目有血有肉吧。2、设计数据库本次练习比较简单,就两个表,一个user表,一个文章表。我们采用python的orm框架flask-sqlalchemy实现表的创建、增删改查功能。在model文件夹中添加User.py和Category.py文件,内容如下:1) User.py:
from blog2 import db
class User(db.Model):
__tablename__ = 'b_user'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(10),unique=True)
password = db.Column(db.String(16))
def __init__(self,username,password):
self.username = username
self.password = password
def __repr__(self):
return '&User %r&' % self.username
2) Category.py
from blog2 import db
class Category(db.Model):
__tablename__ = 'b_category'
id = db.Column(db.Integer,primary_key=True)
title = db.Column(db.String(20),unique=True)
content = db.Column(db.String(100))
def __init__(self,title,content):
self.title = title
self.content = content
def __repr__(self):
return '&Category %r&' % self.title
3)在模块目录blog2下新建setting.py文件,配置数据库连接信息
# _*_ coding: utf-8 _*_
#调试模式是否开启
DEBUG = True
SQLALCHEMY_TRACK_MODIFICATIONS = False
#session必须要设置key
SECRET_KEY='A0Zr98j/3yX R~XHH!jmN]LWX/,&#63;RT'
#mysql数据库连接信息,这里改为自己的账号
SQLALCHEMY_DATABASE_URI = "mysql://username:password@ip:port/dbname"
4)让项目读取配置文件修改__init__.py:添加如下内容(红色部分):
# -*- coding: utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)#import os#print os.environ.keys()#print os.environ.get('FLASKR_SETTINGS')#加载配置文件内容app.config.from_object('blog2.setting')
#模块下的setting文件名,不用加py后缀 app.config.from_envvar('FLASKR_SETTINGS')
#环境变量,指向配置文件setting的路径#创建数据库对象 db = SQLAlchemy(app)
注意:FLASKR_SETTINGS环境变量需要手工单独设置,window下可以在命令行中输入:
E:\workdir\blog2& set FLASKR_SETTINGS=E:\workdir\blog2\blog2\setting.py
或者点击我的电脑--&高级--&环境变量,新建一个。5)创建数据库和表windows命令行模式下,cd到项目runserver.py那个目录下,进入python shell下:输入红色部分:
E:\workdir\blog2&python
Python 2.7.10 (default, May 23 :00) [MSC v.1500 64 bit (AMD64)] on wi
Type "help", "copyright", "credits" or "license" for more information.
&&& from blog2 import db
&&& db.create_all()
如果没有任何错误输出代表创建数据库和表成功了。这时我们到数据库中去查看:
数据库已经存在了,再看看表情况:发现没有对应的b_user和b_category表。这是为什么呢?是不是没有找到model目录下的两个类呢。问题在于:__init__.py文件没有引入model包,导致__init__.py无法找到实体类。记住:一切模块对象的创建都在__init__.py中完成在blog2目录下的__init__.py添加如下代码:
#只有在app对象之后声明,用于导入model否则无法创建表
from blog2.model import User,Category
再次运行上面命令:db.create_all()方法。这时表已经创建成功了。
3、添加界面模板:如登陆页面,显示blog文章页面,添加blog页面在templates目录下添加三个html文件: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 %}
{% for message in get_flashed_messages() %}
&div class=flash&{{ message }}&/div&
{% endfor %}
{% block body %}{% endblock %}
&/div&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&
&dt&Username:
&dd&&input type=text name=username&
&dt&Password:
&dd&&input type=password name=password&
&dd&&input type=submit value=Login&
{% endblock %}
show_entries.html:
{% extends "layout.html" %}
{% block body %}
{% if session.logged_in %}
&form action="{{ url_for('add_entry') }}" method='POST' class=add-entry&
&dt&Title:
&dd&&input type=text size=30 name=title&
&dd&&textarea name=text rows=5 cols=40&&/textarea&
&dd&&input type=submit value=Share&
{% endif %}
&ul class=entries&
{% for entry in entries %}
&li&&h2&{{ entry.title }}&/h2&{{ entry.content|safe }}
{% else %}
&li&&em&Unbelievable. No entries here so far&/em&
{% endfor %}
{% endblock %}
对应static中添加css文件:style.css
{ font-family: sans- background: # }
{ color: #377BA8; }
{ font-family: 'Georgia', margin: 0; }
{ border-bottom: 2px solid # }
{ font-size: 1.2 }
{ margin: 2 width: 35 border: 5px solid #
padding: 0.8 background: }
{ list-style: margin: 0; padding: 0; }
.entries li
{ margin: 0.8em 1.2 }
.entries li h2 { margin-left: -1 }
.add-entry
{ font-size: 0.9 border-bottom: 1px solid # }
.add-entry dl
{ font-weight: }
{ text-align: font-size: 0.8 padding: 0.3
margin-bottom: 1 background: # }
{ background: #CEE5F5; padding: 0.5
border: 1px solid #AACBE2; }
{ background: #F0D6D6; padding: 0.5 }
4、添加业务逻辑在controller目录下新建blog_message.py文件:
from blog2.model.User import User
from blog2.model.Category import Category
from blog2 import app,db
from flask import request,render_template,flash,abort,url_for,redirect,session,Flask,g
@app.route('/')
def show_entries():
categorys = Category.query.all()
return render_template('show_entries.html',entries=categorys)
@app.route('/add',methods=['POST'])
def add_entry():
if not session.get('logged_in'):
abort(401)
title = request.form['title']
content = request.form['text']
category = Category(title,content)
db.session.add(category)
flash('New entry was successfully posted')
return redirect(url_for('show_entries'))
@app.route('/login',methods=['GET','POST'])
def login():
error = None
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = User.query.filter_by(username=request.form['username']).first()
passwd = User.query.filter_by(password=request.form['password']).first()
if user is None:
error = 'Invalid username'
elif passwd is None:
error = 'Invalid password'
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'))千万不要忘了在模块级目录下(blog2目录)的__init__.py文件引入视图模块,代码如下:
#只有在app对象之后声明,用于导入view模块
from blog2.controller import blog_manage5、运行项目,效果如下:1)输入http://127.0.0.1:5000/,正常情况下你的应该是空白的,因为还没有任何数据。
2)点击log in
忘了告诉你了,你要事先在b_user表中添加一个用户喔,因为登陆要验证用户的,否则你是无法登陆成功的。3) 添加条目
&以上就是这个小项目的所有页面,很简单吧。你一定能搞定!!!【总结】:通过本次练习,是否对flask框架运行机制有所了解呢,是不是已经有了全局的认识了,如果ok,那么这个小练习就有存在价值了。参考文献:&&&&&&&& 【flask快速入门中文版】http://docs.jinkan.org/docs/flask/&&&&&&&& 【flask快速入门英文版】http://flask.pocoo.org/docs/0.11/&&&&&&&& 【flask-sqlalchemy中文版】/flask-sqlalchemy/index.html&&&&&&&& 【flask-sqlalchemy英文版】http://flask-sqlalchemy.pocoo.org/2.1/
加: 03:26:01&
更: 01:35:59&
&&网站联系: qq: email:&

我要回帖

 

随机推荐