目标:
将此次目标新建一个Flask项目,项目名为(Todo)
Todo项目包含上图所示文件(migrations:数据库扩展;static:静态文件;templates:html文件;forms:表单处理;manager:数据库扩展;models:连接数据库;run:主函数;views:主函数的路径与视图函数)
主函数(run.py)
from models import app
from views import *
if __name__ == '__main__':
app.run()
主函数的路径与视图函数(views.py)
from flask import render_template, redirect, url_for, request, session
from models import app, Todo, db, Department, User, Userlog
from forms import LoginForm,RegisterForm
import functools
def is_login(f):
"""判断用户是否登陆的装饰器"""
@functools.wraps(f)
def wrapper(*args, **kwargs):
if 'user' not in session:
return redirect('/login/')
return f(*args, **kwargs)
return wrapper
@app.route('/')
def index():
todos=Todo.query.all()
parts=Department.query.all()
return render_template('index.html',
todos=todos,
parts=parts
)
@app.route('/login/',methods=['GET','POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = form.data['user']
passwd = form.data['passwd']
u = User.query.filter_by(name=user).first()
if u.pwd==passwd:
session['user']=u.name
session['user_id']=u.id
# session['user_id']=u.id
userlog=Userlog(
user_id=u.id
)
db.session.add(userlog)
db.session.commit()
return redirect(url_for('todo_list'))
else:
return render_template('login.html', form=form, message='用户名或密码错误')
return render_template('login.html', form=form)
@app.route('/register/',methods=['GET','POST'])
def register():
form=RegisterForm()
if form.validate_on_submit():
user=form.data['user']
passwd=form.data['passwd']
u = User(name=user, pwd=passwd, department_id=1)
db.session.add(u)
db.session.commit()
return redirect(url_for('login'))
return render_template('register.html',form=form)
@app.route('/logout/')
def logout():
return redirect(url_for('index'))
# 任务的增删改查
@app.route('/todo/add/',methods=['POST'])
@is_login
def todo_add():
name=request.form['todo_name']
part=request.form['part']
todo=Todo(name=name,department_id=part,user_id=1)
db.session.add(todo)
db.session.commit()
return redirect(url_for('todo_list'))
@app.route('/todo/delete//')
@is_login
def todo_delete(id):
todo=Todo.query.filter_by(id=id).first()
db.session.delete(todo)
db.session.commit()
return redirect(url_for('todo_list'))
@app.route('/list/')
def todo_list():
#从数据库中查询
todos=Todo.query.all()
parts=Department.query.all()
return render_template('list.html',
todos=todos,
parts=parts
)
# 修改任务状态
@app.route('/todo/undo//')
@is_login
def undo(id):
todo=Todo.query.filter_by(id=id).first()
todo.status=False
db.session.commit()
return redirect(url_for('todo_list'))
@app.route('/todo/done//')
@is_login
def done(id):
todo = Todo.query.filter_by(id=id).first()
todo.status = True
db.session.commit()
return redirect(url_for('todo_list'))
数据库的连接,数据表与数据的初步建立(models.py)
from datetime import datetime
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os
from flask_bootstrap import Bootstrap
app=Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']="mysql+pymysql://root:redhat@localhost/Todo"
app.config['SECRET_KEY'] = os.urandom(24)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db=SQLAlchemy(app)
bootstrap=Bootstrap(app)
class Todo(db.Model):
id=db.Column(db.INTEGER,autoincrement=True,primary_key=True)
name = db.Column(db.String(200),nullable=False)
add_time = db.Column(db.DateTime, default=datetime.now())
status=db.Column(db.BOOLEAN,default=False)
department_id=db.Column(db.INTEGER, db.ForeignKey('department.id'))
user_id=db.Column(db.INTEGER, db.ForeignKey('user.id'))
def __repr__(self):
return ''%(self.name)
class Department(db.Model):
id = db.Column(db.INTEGER, autoincrement=True, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False)
users=db.relationship('User',backref='department')
todos=db.relationship('Todo',backref='department')
def __repr__(self):
return ''%(self.name)
class User(db.Model):
id = db.Column(db.INTEGER, autoincrement=True, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False)
pwd = db.Column(db.String(100))
email = db.Column(db.String(30), unique=True)
info = db.Column(db.TEXT)
add_time = db.Column(db.DateTime, default=datetime.now())
department_id = db.Column(db.INTEGER, db.ForeignKey('department.id'))
todos = db.relationship('Todo', backref='user')
userlogs = db.relationship('Userlog', backref='user')
def __repr__(self):
return ''%(self.name)
class Userlog(db.Model):
id = db.Column(db.INTEGER, autoincrement=True, primary_key=True)
add_time = db.Column(db.DateTime, default=datetime.now())
# ip=db.Column(db.String(200),nullable=False)
# area=db.Column(db.String(200))
user_id = db.Column(db.INTEGER, db.ForeignKey('user.id'))
def __repr__(self):
return ''%(self.name)
if __name__ == '__main__':
db.drop_all()
db.create_all()
parts=['开发部','人事部','运维部']
partObj=[Department(name=part) for part in parts]
db.session.add_all(partObj)
db.session.commit()
u1=User(name='westos',pwd='westos',department_id=1)
db.session.add(u1)
db.session.commit()
表单处理,接收输入框组中的数据(forms.py)
from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,SubmitField
from wtforms.validators import Length,Email,EqualTo,Regexp
class LoginForm(FlaskForm):
user=StringField(
label='用户名',
)
passwd=PasswordField(
label='密码',
)
submit=SubmitField(
label='登陆',
)
class RegisterForm(FlaskForm):
user = StringField(
label="用户名/手机/邮箱",
validators=[
Length(5, 12),
]
)
email = StringField(
label="邮箱",
validators=[
Email("邮箱格式不正确!")
]
)
phone = StringField(
label="电话",
validators=[
Regexp(r'1\d{10}', message="手机格式不正确!")
]
)
passwd = PasswordField(
label="密码",
validators=[
Length(6)
]
)
repasswd = PasswordField(
label="确认密码",
validators=[
EqualTo('passwd', "两次密码不一致!")
]
)
submit = SubmitField(
label="注册"
)
数据库的扩展,数据库扩建时使用,还有一些自定义的函数(manager.py)
from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from models import app, db, User, Department
manager=Manager(app)
migrete=Migrate(app,db)
manager.add_command('db',MigrateCommand)
@manager.command
def show_depart():
"""显示所有部门"""
departs=Department.query.all()
print(departs)
@manager.option('-n','--name',help='添加部门')
def add_depart(name):
"""添加部门"""
try:
depart1=Department(name=name)
db.session.add(depart1)
db.session.commit()
except:
print('添加部门失败')
else:
print('添加部门%s成功'%(name))
if __name__ == '__main__':
manager.run()
templates 中的 html 页面:
base.html
{#自己编写一个基类模板#}
{% extends "bootstrap/base.html" %}
{% block styles %}
{{ super() }}
{% endblock %}
{% block navbar %}
{% endblock %}
{% block content %}
{#定义属于自己的block#}
{% block newcontent %}
{% endblock %}
{% endblock %}
index.html
{% extends 'base.html' %}
{% block title %}
主页
{% endblock %}
{% block newcontent %}
{% endblock %}
login.html
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block title %}
登陆
{% endblock %}
{% block newcontent %}
登录
没有账号?注册
{{ wtf.quick_form(form) }}
{% if message %}
{{message}}
{% endif %}
{% endblock %}
register.html
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}
注册
{% endblock %}
{% block newcontent %}
注册
没有账号?注册
{{ wtf.quick_form(form) }}
{% endblock %}
list.html
{% extends 'base.html' %}
{% block title %}用户显示{% endblock %}
{% block logout %} 登出{% endblock %}
{% block newcontent %}
{% endblock %}
执行结果:
首先进入清单后
此页面下不能添加任务、修改任务和删除任务,只有在登陆状态下,才可以进行,如果非要进行的话,会跳转到登陆页面
先进行登陆
由于初始数据库中只有(用户名和密码都为 westos )的用户,因此密码错误
倘若没有帐号,可以注册一个
注册要求,要符合 forms 表单中的要求,注册成功后,就会调转到登陆页面
在 list 可以执行任务的增加
有新的任务添加成功,默认的状态是未完成
可以进行任务状态的修改
完成看篮球比赛的任务时,可将未完成,改为已完成的状态
主要运用到的就是 上一篇博客说到的 flask、flask_wtf、flask_bootstrap、flask_sqlalchemy、flask_migrate 和 falsk_script 这6个第三方库组成了整个的 Flask 框架