Flask项目——Todo

目标:

实现一个项目,包括用户注册、登陆、登出、用户查询任务列表、任务完成进度、以及任务分类。

创建结构:

.
├── app
│   ├── forms.py
│   ├── __init__.py
│   ├── models.py
│   ├── __pycache__
│   │   ├── forms.cpython-36.pyc
│   │   ├── __init__.cpython-36.pyc
│   │   ├── __init__.cpython-37.pyc
│   │   ├── models.cpython-36.pyc
│   │   └── views.cpython-36.pyc
│   ├── static
│   │   ├── css
│   │   │   └── main.css
│   │   └── js
│   │       └── echarts.min.js
│   ├── templates
│   │   ├── base.html
│   │   ├── login.html
│   │   ├── register.html
│   │   └── todo
│   │       ├── add_todo.html
│   │       ├── edit_todo.html
│   │       ├── list_todo.html
│   │       ├── new_show_todo.html
│   │       └── show_todo.html
│   └── views.py
├── config.py
├── doc(编写所需文档)
├── manage.py
└── migrations
    ├── alembic.ini
    ├── env.py
    ├── __pycache__
    │   └── env.cpython-36.pyc
    ├── README
    ├── script.py.mako
    └── versions

11 directories, 30 files

第一步:

__init__
初始化app对象、db对象、manager对象、bt对象、migrate对象以及moment对象,
并读取config.py中的设置信息:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
from flask_script import Manager
from flask_migrate import Migrate
from flask_moment import Moment
import pymysql

app = Flask(__name__)

# 数据库报错问题
pymysql.install_as_MySQLdb()

# 读取配置文件的配置信息
app.config.from_pyfile('../config.py')
db = SQLAlchemy(app)
manager = Manager(app)
bt = Bootstrap(app)
migrate = Migrate(app, db)
moment = Moment(app)

第二步:

config.py
在mysql中创建Todo的database,编写创建数据表所需要的基本设置:

SQLALCHEMY_DATABASE_URI = 'mysql://root:westos@localhost/Todo'
SQLALCHEMY_TRACK_MODIFICATIONS = True
SECRET_KEY = 'westos'
PER_PAGE = 5

第三步:

models.py
定义三个模型,分别是用户(User)、任务(Todo)、以及任务分类(Category)。
我们需要首先确定:
一个用户对应多个任务;
一个任务分类对应多个任务;
一个用户对应多个任务分类。
(外键写在多的一端)

from app import db
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime


class User(db.Model):
    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    username = db.Column(db.String(20), unique=True)
    password_hash = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(30), unique=True)
    # datetime.now()你当前所在时区的时间
    # 使用协调时间时 (Coordinated Universal Time, UTC) 协调世界各地的时差问题
    # 美国时间: 2019-3-15 00:00   北京时间: 2019-03-16 12:00
    add_time = db.Column(db.DateTime, default=datetime.utcnow())  # 账户创建时间
    # 1). User添加属性todos; 2). Todo添加属性user;
    todos = db.relationship('Todo', backref="user")
    categories = db.relationship('Category', backref='user')

    # *********************************************************************
    @property
    def password(self):
        """u.password"""
        raise AttributeError("密码属性不可以读取")

    @password.setter
    def password(self, password):
        """u.password = xxxxx """
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        """验证密码是否正确"""
        return check_password_hash(self.password_hash, password)
    # *********************************************************************

    def __repr__(self):
        return "<User %s>" % (self.username)


class Todo(db.Model):
    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    content = db.Column(db.String(100))  # 任务内容
    status = db.Column(db.Boolean, default=False)  # 任务的状态
    add_time = db.Column(db.DateTime, default=datetime.utcnow())  # 任务创建时间
    # 任务的类型, 关联另外一个表的id
    category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
    # 任务所属用户
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

    def __repr__(self):
        return "<Todo %s>" % (self.content[:6])


class Category(db.Model):
    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    name = db.Column(db.String(20), unique=True)
    add_time = db.Column(db.DateTime, default=datetime.utcnow())  # 任务创建时间
    # 1). Category添加一个属性todos; 2). Todo添加属性category;
    todos = db.relationship('Todo', backref='category')
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

    def __repr__(self):
        return "<Category %s>" % (self.name)

第四步:

manage.py
编写需要运行的主函数:

from app import manager, db
from app.views import *
from flask_migrate import MigrateCommand
# 添加数据库操作的命令信息
from app.models import User, Category, Todo


@manager.command
def dbinit():
    """数据库初始化信息"""
    db.drop_all()
    db.create_all()
    u = User(username='admin', email="admin@qq.com")
    u.password = 'admin'
    db.session.add(u)
    db.session.commit()
    print("用户%s创建成功......." % (u.username))

    c = Category(name="学习", user_id=1)
    db.session.add(c)
    print("分类%s创建成功...." % (c.name))

    t = Todo(content="学习Flask", category_id=1, user_id=1)
    db.session.add(t)
    print("任务%s添加成功....." % (t.content))
    db.session.commit()


manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
    manager.run()

第五步:

view.py
编写视图函数,定义页面:

import json
from functools import wraps
from app import app, db
# 网站首页
from app.forms import RegisterForm, LoginForm, AddTodoForm, EditTodoForm
from flask import render_template, flash, redirect, url_for, session, request
from app.models import User, Todo


def is_login(f):
    """用来判断用户是否登录成功"""
    @wraps(f)
    def wrapper(*args, **kwargs):
        # 判断session对象中是否有seesion['user'],
        # 如果包含信息, 则登录成功, 可以访问主页;
        # 如果不包含信息, 则未登录成功, 跳转到登录界面;;
        if session.get('user', None):
            return f(*args, **kwargs)
        else:
            flash("用户必须登录才能访问%s" % (f.__name__))
            return redirect(url_for('login'))
    return wrapper


# 主页信息
@app.route('/')
def index():
    return redirect(url_for('list'))


# 注册页面
@app.route('/register/', methods=['POST', 'GET'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        # 1. 从前端获取用户输入的值;
        email = form.email.data
        username = form.username.data
        password = form.password.data
        # 2. 判断用户是否已经存在? 如果返回位None,说明可以注册;
        u = User.query.filter_by(username=username).first()
        if u:
            flash("用户%s已经存在" % (u.username))
            return redirect(url_for('register'))
        else:
            u = User(username=username, email=email)
            u.password = password
           
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值