Web前端之Flask框架--任务清单管理系统(四:任务管理)

一、数据库模型

  • 用户信息修改
  • 添加任务清单
  • 添加任务分类

app/models.py

class User(UserMixin, db.Model): 
    """用户""" 
    # ....... 
    # 1). Category添加一个属性todos, 2). Todo添加属性category; 
    todos = db.relationship('Todo', backref='user') 
    # ........
class Todo(db.Model):
    __tablename__='todos'
    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,因为分类:任务=1:N,外键写在多的一端
    category_id=db.Column(db.Integer,db.ForeignKey('categories.id'))
    # 任务所属用户,用户:任务=1:N,因此外键写在任务一端,关联的是用户表的id
    user_id=db.Column(db.Integer,db.ForeignKey('users.id'))

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


class Category(db.Model):
    __tablename__='categories'
    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:N
    user_id=db.Column(db.Integer,db.ForeignKey('users.id'))
    # 反向引用:1)Category添加todos属性 2)Todo添加categories属性
    todos=db.relationship('Todo',backref='category')


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

二、表单文件

  • 添加任务的表单
  • 编辑任务的表单
  • 添加分类的表单

app/todo/forms.py

from flask_wtf import FlaskForm
from wtforms import StringField,SelectField,SubmitField
from wtforms.validators import DataRequired
from app.models import Category


class AddTodoForm(FlaskForm):
    content=StringField(
        label='任务内容',
        validators=[DataRequired()],
        render_kw={
            'class':'form-control',
            'placeholder':'添加任务信息'
        }
        # 当使用宏时,租用类名为form-control的模板,在list.html中
    )
    # 下拉表
    category=SelectField(
        label='任务类型',
        coerce=int ,
        # choice=[(item.id,item.name) for item in Category.query.all()]
        render_kw={
            'class':'btn btn-choice dropdown-toggle',
            'type': "button",
            'data-toggle': "dropdown",
            'aria-haspopup': "true",
            'aria-expanded': "false"
        }
    )
    submit=SubmitField(
        label='添加任务',
        render_kw={
            'class':'btn btn-default btn-todo-add'
        }
    )

    # 构造方法在实例化对象时自动执行,这里在每次实例化表单对象时,都会重新查询所有的分类,并展示在下拉表中
    def __init__(self):
        # 执行父类的构造方法
        super(AddTodoForm, self).__init__()
        categories=Category.query.all()
        if categories:
            self.category.choices=[(item.id,item.name) for item in categories]
        else:
            self.category.choices=[(-1,'请先创建分类')]


class EditTodoForm(FlaskForm):
    content=StringField(
        label='任务内容',
        validators=[DataRequired()]
    )
    category=SelectField(
        label='任务类型',
        coerce=int,
    )
    submit=SubmitField(
        label='编辑任务',
    )

    def __init__(self):
        super(EditTodoForm, self).__init__()
        categories=Category.query.all()
        if categories:
            self.category.choices=[(item.id,item.name) for item in categories]
        else:
            self.category.choices=[-1,'请先创建分类']

class AddCategoryForm(FlaskForm): 
    content = StringField(
        label='分类名称', 
        validators=[DataRequired()] 
    )
    submit = SubmitField( 
         label='添加分类', 
    ) 

三、视图函数文件

app/todo/views.py

# 查看任务
@todo.route('/list/')
@login_required
def list():
    form = AddTodoForm()  # 添加任务之前首先有一个表单,这里实例化了在forms文件中的表单类
    # 任务显示需要分页,每个用户只能查看自己的任务
    page=int(request.args.get('page',1))   # request获取用户传入的参数,由于页数是整型,所以int()
    todoPageobj=Todo.query.filter_by(
        user_id=current_user.id).paginate(
        # 在config.py文件中设置PER_PAGE=5
        # paginate设置分页,page表示显示几页,per_page表示显示多少条数据
        page,per_page=current_app.config['PER_PAGE']
    )
    return render_template('todo/list.html',todoObj=todoPageobj,form=form)


@todo.route('/add',methods=['POST'])
# 用get方法获取表单页面,post方法提交一些用户输入的新的数据
@login_required
def add():
    form = AddTodoForm()  # 添加任务之前首先有一个表单,这里实例化了在forms文件中的表单类
    if form.validate_on_submit():
        # 获取用户提交的内容
        content=form.content.data
        # 这里虽然填入的是字符串,但是实际存入的是任务id,是由于forms文件中coerce=int的设置
        category_id=form.category.data
        # 添加到数据库中
        todo=Todo(
            content=content,
            category_id=category_id,
            user_id=current_user.id
        )
        db.session.add(todo)
        db.session.commit()
        # 闪现信息没有显示,需要在add.html中include一下
        flash('添加任务成功',category='success')
        return redirect(url_for('todo.list'))
    print(Category.query.all())


@todo.route('/edit/<int:id>/',methods=['GET','POST'])
def edit(id):
    form=EditTodoForm()
    # ****重要**** 编辑任务时需要获取原先任务的信息,并显示到表单里面
    todo=Todo.query.filter_by(id=id).first()
    form.content.data=todo.content
    form.category.data=todo.category_id
    if form.validate_on_submit():
        # 更新时获取表单数据一定要使用request.form方法获取,
        # 而form.content.data并不能获取用户更新后提交的表单内容;
        content=request.form.get('content')
        category_id=request.form.get('category')
        # 更新到数据库里面
        todo.content=content
        todo.category_id=category_id
        db.session.add(todo)
        db.session.commit()
        flash('任务已更新',category='success')
        return redirect(url_for('todo.list'))
    return render_template('todo/edit.html',form=form)


# 删除任务,根据任务id删除
@todo.route('/delete/<int:id>')
@login_required
def delete(id):
    todo=Todo.query.filter_by(id=id).first()
    db.session.delete(todo)
    db.session.commit()
    flash('删除任务成功',category='success')
    return redirect(url_for('todo.list'))


# 修改任务状态为完成
@todo.route('/done/<int:id>')
@login_required
def done(id):
    todo=Todo.query.filter_by(id=id).first()
    todo.status=True
    db.session.add(todo)
    db.session.commit()
    flash('修改状态成功',category='success')
    return redirect(url_for('todo.list'))


# 修改任务状态为未完成
@todo.route('/undo/<int:id>')
@login_required
def undo(id):
    todo=Todo.query.filter_by(id=id).first()
    todo.status=False
    db.session.add(todo)
    db.session.commit()
    flash('修改状态成功',category='success')
    return redirect(url_for('todo.list'))



@todo.route('/category/add/', methods=['GET', 'POST']) 
@login_required 
def category_add(): 
    form = AddCategoryForm() 
    if form.validate_on_submit(): 
	# 获取用户提交的内容 
	content = form.content.data 
	# 添加到数据库中
	category = Category(name=content, 	
			    user_id=current_user.id 
			    ) 
	db.session.add(category) 
	flash('添加分类成功', category='success') 
	return redirect(url_for('todo.category_add')) 
    print(Category.query.all()) 
    return render_template('todo/category_add.html', form=form) 



# 查看任务 
@todo.route('/category/list/') 
@login_required 
def category_list(page=1): 
    print(page) 
    # 任务显示需要分页,每个用户只能查看自己的任务 
    categoryPageObj = Category.query.filter_by( 
        user_id=current_user.id).paginate( 
        # 在config.py文件中有设置; 
        page, per_page=current_app.config['PER_PAGE']) 
        return render_template('todo/category_list.html', categoryPageObj=categoryPageObj) 

四、分页展示

  • 视图函数
    app/todo/views.py
# 查看任务
@todo.route('/list/')
@login_required
def list():
    form = AddTodoForm()  # 添加任务之前首先有一个表单,这里实例化了在forms文件中的表单类
    # 任务显示需要分页,每个用户只能查看自己的任务
    page=int(request.args.get('page',1))   # request获取用户传入的参数,由于页数是整型,所以int()
    todoPageobj=Todo.query.filter_by(
        user_id=current_user.id).paginate(
        # 在config.py文件中设置PER_PAGE=5
        # paginate设置分页,page表示显示几页,per_page表示显示多少条数据
        page,per_page=current_app.config['PER_PAGE']
    )
    return render_template('todo/list.html',todoObj=todoPageobj,form=form)
  • 前端页面
{% if paginate.has_prev %} 
     <a href="{{ url_for('user.list') }}?page={{ paginate.prev_num }}">上一页</a> 
{% endif %} 

{% for i in paginate.iter_pages() %} 
     <a href="{{ url_for('user.list') }}?page={{ i }}"> 
	{% if not i %} 
	    ... 
	{% else %} 
	    {{ i }} 
	{% endif %} 
     </a> 
{% endfor %} 

{% if paginate.has_next %} 
     <a href="{{ url_for('user.list') }}?page={{ paginate.next_num }}">下一页</a> 
{% endif %}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值