python画鱼教程_Python Flask高级编程之从0到1开发《鱼书》精品项目 学习 教程??
一 、安装环境
我们使用 flask web框架,并用 sqlalchemy来做数据库映射,并使用 migrate做数据迁移。
$ pip install flask
$ pip install SQLAlchemy==0.7.9
$ pip install flask-sqlalchemy
$ pip install flask-migrate
$ pip install sqlalchemy-migrate
二、建立项目
flask 没有 django 那样原生的 manage管理工具(flask-admin可以实现,日后再说)。因此我们需要手动建立目录。新建一个 myproject目录,在里面建 app tmp两个文件夹,然后在 app文件夹里面建立 static, templates 两个文件夹,用来存储静态文件和模板。最后目录结构如下:
├── app
│ ├── static
│ ├── templates
└── tmp
三、 初始化文件
建立一些文件,在 app文件里建立 __init__.py models.py views.py 然后在与app 同目录下建立 config.py 和 run.py 此时的目录结构如下:
(env)admin@admindeMacBook-Air:~/project/python/flask/project$ tree
├── app
│ ├── static
│ ├── templates
│ ├── __init__.py
│ ├── models.py
│ ├── views.py
├── config.py
├── run.py
└── tmp
四 、开始项目
1 hello wrod
打开 (/app/__init.py) 文件,写入
# -*- coding: utf-8 -*-
from flask import Flask # 引入 flask
app = Flask(__name__) # 实例化一个flask 对象
import views # 导入 views 模块
# from app import views
注意,我们的 app 文件夹其实是一个python包,from app import views 这句话也就是从 包app里面导入 views模块,所以写成注释的那句话也没错,其他代码实践喜欢写成后面那种
现在我们来开始写我们的视图,打开 (/app/views.py)
# -*- coding: utf-8 -*-
from app import app
from models import User, Post, ROLE_USER, ROLE_ADMIN
@app.route(‘/’)
def index():
return ‘hello world, hello flask’
下一步我们将要启动我们的开发服务器,打开 (/run.py)
# -*- coding: utf-8 -*-
from app import app
if __name__ == ‘__main__’:
app.debug = True # 设置调试模式,生产模式的时候要关掉debug
app.run() # 启动服务器
这段代码需要注意第一句 from app import app。也许会有疑问,我们的 app 包里,貌似没有 app.py 这样的模块。其实这是 flask 方式和python的导入方式。from app 指导入 app 包里的 __iniy__.py 所以这句话的含义是导入 __.init__.py 里面的 app实例。
打开shell 运行
$ python run.py
(env)admin@admindeMacBook-Air:~/project/python/flask/project$ python run.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader
用浏览器打开 http://127.0.0.1:5000/ 将会看到一个输入 hello world 的页面
2 连接数据库
下面开始连接数据库引擎 先要做一个简单的配置 打开 (/config.py)
# -*- coding: utf-8 -*-
import os
basedir = os.path.abspath(os.path.dirname(__file__))
SQLALCHEMY_DATABASE_URI = ‘sqlite:///%s’ % os.path.join(basedir, ‘app.db’)
SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, ‘db_repository’)
CSRF_ENABLED = True
SECRET_KEY = ‘you-will-never-guess’
SQLALCHEMY_DATABASE_URI是the Flask-SQLAlchemy必需的扩展。这是我们的数据库文件的路径。
SQLALCHEMY_MIGRATE_REPO 是用来存储SQLAlchemy-migrate数据库文件的文件夹。
然后打开 (/app/__init__.py)
# -*- coding: utf-8 -*-
import os
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from config import basedir
app = Flask(__name__)
app.config.from_object(‘config’) # 载入配置文件
db = SQLAlchemy(app) # 初始化 db 对象
# from app import views, models # 引用视图和模型
import views, models
打开 (/app/models.py)
# -*- coding: utf-8 -*-
from app import db
ROLE_USER = 0
ROLE_ADMIN = 1
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
nickname=db.Column(db.String(60), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
role = db.Column(db.SmallInteger, default=ROLE_USER)
def __repr__(self):
return ‘’ % self.nickname
我们的模型建立了一个 user类,正好是 数据库里面的 user 表,表有四个字段
现在我们的数据库配置已经好了,可是还没有建立数据库。新建一个文件 (/db_create.py)
# -*- coding: utf-8 -*-
from migrate.versioning import api
from config import SQLALCHEMY_DATABASE_URI
from config import SQLALCHEMY_MIGRATE_REPO
from app import db
import os.path
db.create_all()
if not os.path.exists(SQLALCHEMY_MIGRATE_REPO):
api.create(SQLALCHEMY_MIGRATE_REPO, ‘database repository‘)
api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
else:
api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, api.version(SQLALCHEMY_MIGRATE_REPO))
这个脚本是完全通用的,所有的应用路径名都是从配置文件读取的。当你用在自己的项目时,你可以把脚本拷贝到你的项目目录下就能正常使用了。
打开shell 运行
$ python db_create.py
运行这条命令之后,你就创建了一个新的app.db文件。这是个支持迁移的空sqlite数据库,同时也会生成一个带有几个文件的db_repository目录,这是SQLAlchemy-migrate存储数据库文件的地方,注意如果数据库已存在它就不会再重新生成了。这将帮助我们在丢失了现有的数据库后,再次自动创建出来。
运行
slqite3 app.db
>>> .tables
>>> user
或者使用 sqlite 图形化客户端,没有需要安装 (windows 下直接下载安装包即可)
$ sudo apt-get install sqlitebrowser
3 数据库迁移
每当我们更改了 models 。等价于更改了数据库的表结构,这个时候,需要数据库同步。新建 (/db_migrate.py)
# -*- coding: utf-8 -*-
import imp
from migrate.versioning import api
from app import db
from config import SQLALCHEMY_DATABASE_URI
from config import SQLALCHEMY_MIGRATE_REPO
migration = SQLALCHEMY_MIGRATE_REPO + ‘/versions/%03d_migration.py‘ % (api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) + 1)
tmp_module = imp.new_module(‘old_model‘)
old_model = api.create_model(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
exec old_model in tmp_module.__dict__
script = api.make_update_script_for_model(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, tmp_module.meta, db.metadata)
open(migration, ‘wt‘).write(script)
api.upgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
print ‘New migration saved as‘ + migration
print ‘Current database version:‘ + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO))
这个脚本看起来很复杂,SQLAlchemy-migrate通过对比数据库的结构(从app.db文件读取)和models结构(从app/models.py文件读取)的方式来创建迁移任务,两者之间的差异将作为一个迁移脚本记录在迁移库中,迁移脚本知道如何应用或者撤销一次迁移,所以它可以方便的升级或者降级一个数据库的格式。
开始数据库迁移
$ python db_mirgate.py
New migration saved as db_repository/versions/001_migration.py Current database version: 1
相应的,我们继续创建数据库 升级和回退的脚本
(/db_upgrade.py)
# -*- coding: utf-8 -*-
from migrate.versioning import api
from config import SQLALCHEMY_DATABASE_URI
from config import SQLALCHEMY_MIGRATE_REPO
api.upgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
print ‘Current database version:‘ + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO))
(/db_downgrade.py)
# -*- coding: utf-8 -*-
from migrate.versioning import api
from config import SQLALCHEMY_DATABASE_URI
from config import SQLALCHEMY_MIGRATE_REPO
v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
api.downgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, v – 1)
print ‘Current database version:‘ + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO))
4 操作数据库
接下来,我们定义一个新的models class 并做第二次迁移归并
打开(/app/models.py)
# -*- coding: utf-8 -*-
from app import db
ROLE_USER = 0
ROLE_ADMIN = 1
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
nickname=db.Column(db.String(60), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
role = db.Column(db.SmallInteger, default=ROLE_USER)
posts = db.relationship(‘Post’, db.backref = ‘author’, db.lazyload = ‘dynamic’)
def __repr__(self):
return ‘’ % self.nickname
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey(‘user.id’))
def __repr__(self):
return ‘’ % (self.body)
这里我们进行了两个class 的关联。
$ python db_mirgrate.py
New migration saved as db_repository/versions/002_migration.py Current database version: 2
打开 (/app/views.py)
# -*- coding: utf-8 -*-
from flask import render_template, flash, redirect, session, url_for, request, g
from app import app, db
from models import User, Post, ROLE_USER, ROLE_ADMIN
@app.route(‘/’)
def index():
return render_template(‘index.html’)
@app.route(‘/adduser//’)
def adduser(nickname, email):
u = User(nickname=nickname, email=email)
try:
db.session.add(u)
db.session.commit()
return ‘add successful’
except Exception, e:
return ‘something go wrong’
@app.route(‘/getuser/’)
def getuser(nickname):
user = User.query.filter_by(nickname=nickname).first()
return render_template(‘user.html’, user=user)
@app.errorhandler(404)
def internal_error(error):
return render_template(‘404.html’), 404
@app.errorhandler(500)
def internal_error(error):
db.session.rollback()
return render_template(‘500.html’), 500
这次我们使用了模板, 新建(/app/templates/user.html)
user
user
- user: {{ user.nickname }}
- email: {{ user.email }}
最后运行
$ python run.py
用浏览器访问 http://127.0.0.1:5000/adduser/username/useremail
最后还可以用 sqlite 客户端打开查看我们的数据库变换。关于更多的数据库操作方法,请阅读 sqlalchemy文档。
最后我们的代码目录结构如下:
(env)admin@admindeMacBook-Air:~/project/python/flask/project$ tree
.
├── app
│ ├── __init__.py
│ ├── models.py
│ ├── static
│ ├── templates
│ │ ├── 404.html
│ │ ├── 500.html
│ │ ├── index.html
│ │ └── user.html
│ ├── views.py
├── app.db
├── config.py
├── db_create.py
├── db_downgrade.py
├── db_migrate.py
├── db_repository
│ ├── __init__.py
│ ├── manage.py
│ ├── migrate.cfg
│ ├── README
│ └── versions
│ ├── 001_migration.py
│ ├── 002_migration.py
│ ├── __init__.py
├── db_upgrade.py
├── requirements.txt
├── run.py
├── tmp
5 表单
接下来,我们将要接触表单方面的内容。flask原生提供的表单处理,也比较简单。当然,有了轮子,我们就直接用好了。需要安装一个
Flask-WTF==0.9.4。
安装完之后,打开 (/app/forms.py)
# -*- coding: utf-8 -*-
import re
from flask_wtf import Form
from flask_wtf.html5 import EmailField
from wtforms import TextField, PasswordField, BooleanField
from wtforms.validators import DataRequired, ValidationError
from models import User
from hashlib import md5
class RegisterFrom(Form):
nickname = TextField(‘nickname’, validators=[DataRequired()])
email = EmailField(’email’, validators=[DataRequired()])
password = PasswordField(‘password’, validators=[DataRequired()])
conform = PasswordField(‘conform’, validators=[DataRequired()])
def validate_nickname(self, field):
nickname = field.data.strip()
if len(nickname) < 3 or len(nickname) > 20:
raise ValidationError(‘nickname must be 3 letter at least’)
elif not re.search(r’^\w+$’, nickname):
raise ValidationError(‘User names can contain only alphanumeric characters and underscores.’)
else:
# 验证是否已经注册
u = User.query.filter_by(nickname=nickname).first()
if u:
raise ValidationError(‘The nickname already exists’)
def validate_email(self, field):
email = field.data.strip()
email = User.query.filter_by(email=email).first()
if email:
raise ValidationError(‘The email already exists’)
def validate_password(self, field):
password = field.data.strip()
if len(password) < 6:
raise ValidationError(‘password must be 3 letter at least’)
def validate_conform(self, field):
conform = field.data.strip()
if self.data[‘password’] != conform:
raise ValidationError(‘the password and conform are different’)
上述代码定义了一个 RegisterFrom class,正好是一个表单,class的字段映射为表单的域。其中 wtforms 中有 TextField, PasswordField, BooleanField这些表单类型,flask_wtf.html5 中 EmailField 则是 html5 规范的。
表单有 form.validate_on_submit() 方法,这个方法执行之前会验证表单域。验证方法和django类似,都是 validate_field 的方法。其中一个参数 field正好是表单的value值 需要注意验证两次密码是否相同的时候,需要用到 self.data 。这是一个字典,包含了表单域的name和value
6 用户注册
打开(/app/views.py)添加注册方法。
@app.route(‘/account/signup’, methods=[‘GET’, ‘POST’])
def signup():
form = RegisterFrom()
if request.method == ‘POST’:
if form.validate_on_submit():
psdmd5 = md5(form.data[‘password’])
password = psdmd5.hexdigest()
u = User(nickname=form.data[‘nickname’], email=form.data[’email’], password=password)
try:
db.session.add(u)
db.session.commit()
flash(‘signup successful’)
except Exception, e:
return ‘something goes wrong’
return redirect(url_for(‘signin’))
return render_template(‘signup.html’, form=form)
模版 新建 (/app/tempaltes/signup.html)
{% extends “base.html” %}
{% block content %}
{{ form.hidden_tag() }}
{{ form.nickname.label }} {{ form.nickname(size=20) }}
{{ form.email.label }} {{ form.email(size=20) }}
{{ form.password.label }} {{ form.password(size=20) }}
{{ form.conform.label }} {{ form.conform(size=20) }}
{{ form.errors }}
{% endblock %}
其中,主要是用到 form 对象的一些属性。form.nickname.label 是指表单类定义的名字,form.nickname 会转变成 表单域的 html 代码 即
7 用户登录
先添加一个用户登录的表单,打开 (/app/forms.py)
class LoginForm(Form):
nickname = TextField(‘nickname’, validators=[DataRequired()])
password = PasswordField(‘password’, validators=[DataRequired()])
remember_me = BooleanField(‘remember_me’, default=False)
def validate_nickname(self, field):
nickname = field.data.strip()
if len(nickname) < 3 or len(nickname) > 20:
raise ValidationError(‘nickname must be 3 letter at least’)
elif not re.search(r’^\w+$’, nickname):
raise ValidationError(‘User names can contain only alphanumeric characters and underscores.’)
else:
return nickname
用户登录,最简单的方法就是 验证用户名,如果通过,则添加 session,登出的时候,清除session即可,模版里面可以直接使用 request.session用来判断用户登录状态
打开(/app/views.py) 添加登录登出方法
@app.route(‘/account/signin’, methods=[‘GET’, ‘POST’])
def signin():
form = LoginForm()
if request.method == ‘POST’:
if form.validate_on_submit():
nickname = form.data[‘nickname’]
psdmd5 = md5(form.data[‘password’])
password = psdmd5.hexdigest()
u = User.query.filter_by(nickname=nickname, password=password).first()
if u:
session[‘signin’] = True
flash(‘signin successful’)
return redirect(url_for(‘index’))
else:
flash(u’用户名或者密码错误’)
return render_template(‘signin.html’, form=form)
@app.route(‘/account/signout’)
def signout():
session.pop(‘signin’, None)
flash(‘signout successful’)
return redirect(‘index’)
注意,我们使用 flask 的时候,用了中文,就必须是 unicode
除了原生的登录方式,我们还可以用flask-login。安装flask-login
此时需要初始化一个 login_manager 对象,打开 (/app/__init__.py)
# -*- coding: utf-8 -*-
import os
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.login import LoginManager
from config import basedir
app = Flask(__name__)
app.config.from_object(‘config’)
db = SQLAlchemy(app) # 初始化数据库管理对象
login_manager = LoginManager() # 初始化登录管理对象
login_manager.init_app(app)
login_manager.login_view = “signin” # 登录跳转视图
login_manager.login_message = u”Bonvolu ensaluti por uzi tio pa?o.” # 登录跳转视图前的输出消息
# from app import views, models
import views, models
然后打开 (/app/views.py)
添加下面方法, 注释掉之前的 登入登出方法
from flask.ext.login import login_user, logout_user, current_user, login_required
from app import app, db, login_manager
@login_manager.user_loader
def load_user(userid):
return User.query.get(userid)
@app.route(‘/account/signin’, methods=[‘GET’, ‘POST’])
def signin():
form = LoginForm()
if request.method == ‘POST’:
if form.validate_on_submit():
nickname = form.data[‘nickname’]
psdmd5 = md5(form.data[‘password’])
password = psdmd5.hexdigest()
remember_me = form.data[‘remember_me’]
user = User.query.filter_by(nickname=nickname, password=password).first()
if user:
login_user(user, remember = remember_me)
flash(‘signin successful’)
return redirect(request.args.get(“next”) or url_for(“index”))
else:
flash(u’用户名或者密码错误’)
return render_template(‘signin.html’, form=form)
@app.route(‘/account/signout’)
@login_required
def signout():
logout_user()
flash(‘signout successful’)
return redirect(‘index’)
模版也会响应的改,具体看源码吧。
base.html
{% if title %}
{{title}} – microblog
{% else %}
microblog
{% endif %}
Home
{% if current_user.is_authenticated() %}
signout
{% else %}
signin
{% endif %}
{% for message in get_flashed_messages() %}
{% endfor %}
{% block content %}{% endblock %}
python画鱼教程_Python Flask高级编程之从0到1开发《鱼书》精品项目 学习 教程??相关推荐
- python flask高级编程之restful_('Python Flask高级编程之RESTFul API前后端分离精讲',),全套视频教程学习资料通过百度云网盘下载...
资源详情 r n t某课网好评度100%的Python Flask高级编程之RESTFul API前后端分离精讲 r n t t t第1章 随便聊聊 r n t t t聊聊Flask与Django,聊 ...
- python flask restful入门_Python Flask高级编程之RESTFul API前后端分离精讲
第1章 随便聊聊 聊聊Flask与Django,聊聊代码的创造性1-1 Flask VS Django 1-2 课程更新维护说明 第2章 起步与红图 本章我们初始化项目,探讨与研究Flask的默认层级 ...
- python flask高级编程之restful_python Flask实现restful api service
一直在用node.js做后端,要逐步涉猎大数据范围,注定绕不过python,因此决定把一些成熟的东西用python来重写,一是开拓思路.通过比较来深入学习python:二是有目标,有动力,希望能持之以 ...
- python爬取美女_Python爬取高颜值美女(爬虫+人脸检测+颜值检测)附学习教程
1 数据源 知乎话题『美女』下所有问题中回答所出现的图片 2 抓取工具 Python 3,并使用第三方库 Requests.lxml.AipFace,代码共 100 + 行 3 必要环境Mac / L ...
- python flask高级编程之restful_flask-restful使用总结
flask-restful是一个用于快速创建restful api接口的flask扩展.使用flask-restful可以很快速方便地创建一个restful风格的接口应用程序. 1.安装 pip in ...
- Spring Boot + vue-element 开发个人博客项目实战教程(一、项目介绍和规划)
⭐ 作者简介:码上言 ⭐ 代表教程:Spring Boot + vue-element 开发个人博客项目实战教程 ⭐专栏内容:零基础学Java.个人博客系统 ⭐我的文档网站:http://xyhwh- ...
- python画pr曲线_python 画函数曲线示例
python 画函数曲线示例 如下所示: import numpy as np import matplotlib.pyplot as plt x = np.linspace(0, 2 * np.pi ...
- unix环境高级编程之 read与write 函数详解
学习记录:unix环境高级编程之 read 与write 函数详解 备注:本博文非本人所写,本人觉得此文讲的非常地道通俗易懂,所以摘录在此以方便以后再次查看 read函数从打开的设备或文件中读取数据 ...
- Spring Boot + vue-element 开发个人博客项目实战教程(二十五、项目完善及扩展(前端部分))
⭐ 作者简介:码上言 ⭐ 代表教程:Spring Boot + vue-element 开发个人博客项目实战教程 ⭐专栏内容:零基础学Java.个人博客系统 ⭐我的文档网站:http://xyhwh- ...
最新文章
- leveldb源码分析:数据插入续(跳表)
- Android meta作用,Android中meta-data的使用
- python pip download_Python Pip 参考手册 - pip download 命令
- 回溯算法 思路清晰,通俗易懂!!!!!!!
- 解决Mysql数据量大的时候 分页优化(使用limit)的问题
- D - Maze(深度搜索+思维转换)
- vue 手机号正则表达式
- 高通9008刷机大法,避坑指南,救砖前提
- 计算机日志文件事件ID,系统日志出现事件 ID:16001来源:AFD的警告
- 邮箱smtp服务-QQ邮箱163邮箱(保姆级图文)【杂记】
- mysql analyze_MySQL数据库执行analyze采集信息
- 【渝粤题库】陕西师范大学201601《中国古代文学(三)》作业 (高起本)
- 数仓可视化,低代码开发平台
- vue项目中使用@babel/plugin-proposal-optional-chaining的?.语法,防止字段没有报错
- 世纪安图招募汉化志愿者
- Python基础 第五章
- 计算机网络与通信之局域网
- 第四课 尚硅谷Scala语言学习-面向对象
- python监控短信_利用Python实现手机短信监控通知的方法
- 百度API的基本介绍和使用场景
热门文章
- 英汉字典程序C语言,电子英汉字典_c语言版.doc
- vscode latex 字数统计
- DO接口测试工装研究
- 125 · 背包问题(二)Backpack II
- Informatica PowerCenter 简介(一)
- 关于NFT房地产:2022年你所需要知道的一切
- ButterKnife与Fragment的爱恨情仇(java.lang.IllegalStateException: Bindings already cleared.)
- cocos creator粒子不变色_Cocos Creator 3D 粒子系统初战: 不要钱的酷炫火焰拿走不谢!...
- 关于“拜占庭将军算法”byzantine generals problem
- vue解决-4048报错