在Flask中的视图函数之间传递对象

时间:2018-07-30 15:15:42

标签: python flask

我正在用Flask编写任务管理应用程序,并且存在以下问题。

当用户登录时,他们会看到项目列表和所有任务的列表。当他们单击项目时,我希望切换视图,以便他们只看到属于该项目的任务。

目前,我有一个可以运行的系统,但是它有一些重复的代码,我认为必须有更好的解决方法。

This是用户登录时立即看到的视图。其中包含所有任务的列表以及他们创建的项目的列表。

对此的查看功能为home()

@tasks.route('/', methods=['GET', 'POST'])
@login_required
def home():
    user = current_user
    form = NewTaskForm(user=current_user)
    if form.validate_on_submit():
        task = Task(body=form.body.data, due=form.due.data, author=current_user._get_current_object(), project=Project.query.filter_by(id=form.project_id.data).first())
        db.session.add(task)
        db.session.commit()
        flash('Your task has been added!')
    form.body.data = ''
    form.due.data = ''
    tasks = Task.query.filter_by(author_id=current_user.id)
    projects = current_user.projects
    return render_template('tasks/home.html', form=form, tasks=tasks, projects=projects)

此函数返回时呈现的模板如下:

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}Tasky - Home{% endblock %}

{% block scripts %}
{{ super() }}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
{% endblock %}

{% block page_content %}
<div class="container">
    <div class="page-header">
        <h1>Welcome back {{ current_user.username }}</h1>
    </div>

    <div class="col-md-4">
        <ul class="list-group">
            <li class="list-group-item">
                <a href="{{ url_for('tasks.status', task_status='today') }}">
                    Today
                </a>
            </li>
            <li class="list-group-item"><a href="{{ url_for('tasks.status', task_status='this_week') }}">This Week</a></li>
            <li class="list-group-item"><a href="{{ url_for('tasks.status', task_status='overdue') }}">Overdue</a></li>
        </ul>
        <ul class="list-group">
            {% for project in projects%}
            <li class="list-group-item">
                <a href="{{ url_for('tasks.project', project_id=project.id) }}">
                    {{ project.name }}
                    <span class="badge">
                        {{ project.tasks.count() }}
                    </span>
                </a>
            </li>
            {% endfor %}
        </ul>
    </div>

    <div class="col-md-8">
        <h2>Add new task:</h2>
        <form class="form-inline" method="post" role="form">
            {{ form.hidden_tag() }}
            {{ wtf.form_errors(form, hiddens="only") }}
            {{ form.body(class="form-control", placeholder="New Task") }}
            {{ form.due(class="form-control", placeholder="dd/mm/yyy") }}
            {{ form.project_id(class="form-control")}}
            {{ form.submit(class="form-control") }}
        </form>
        <hr>
        <h2>My Tasks</h2>
        {% include "tasks/_tasks.html" %}
    </div>
</div>
{% endblock %}

此模板包括下面的_tasks.html部分模板。

<table class="table">

    {% for task in tasks %}
    <tr>
        <td {% if task.done %}style="text-decoration: line-through;" {% endif %}>{{ task.body }}</td>
        <td>{{ task.due.date().__format__('%d/%m/%Y') }}</td>
        <td>
            <span class="label label-info">
                {{ task.project.name }}
            </span>
        </td>
        <td>
            {% if task.done %}
            <span  class="label label-default">Completed</span>
            {% else %}
            <a href="{{ url_for('tasks.complete', task_id=task.id) }}">
                <span  class="label label-primary">Done</span>
            </a>
            {% endif %}
        </td>
        <td>
            <a href="{{ url_for('tasks.delete', task_id=task.id) }}">
                <span class="label label-danger">Delete</span>
            </a>
        </td>
    </tr>
    {% endfor %}
</table>

当用户单击侧栏中的任何项目时,我希望此页面上显示的任务列表发生更改,并仅显示分配给所选项目的任务。我通过创建此新视图功能project()来重新实现了上面的模板,从而完成了此任务。但这需要大量重用的代码来验证表单并列出用户项目。

@tasks.route('projects/<int:project_id>', methods=['GET', 'POST'])
@login_required
def project(project_id):
    user = current_user
    form = NewTaskForm(user=current_user)
    if form.validate_on_submit():
        task = Task(body=form.body.data, due=form.due.data, author=current_user._get_current_object(), project=Project.query.filter_by(id=form.project_id.data).first())
        db.session.add(task)
        db.session.commit()
        flash('Your task has been added!')
    form.body.data = ''
    form.due.data = ''
    tasks = Task.query.filter_by(project_id=project_id)
    projects = current_user.projects
    return render_template('tasks/home.html', form=form, tasks=tasks, projects=projects)

我真正想做的是让project()返回传递给home()或类似的东西的任务列表,这样我就可以摆脱所有重复的代码。我只需要再次渲染任务,页面上的所有其他组件都可以保持不变。

任何对此的建议将不胜感激。

1 个答案:

答案 0 :(得分:0)

您最好的解决方案是,将project_id设为 home 路由的可选参数,从而对两条路由使用相同的功能。 This question有更多详细信息,还有Flask documentation中的示例链接。

将项目作为可选参数可以使您在主视图中不显示所有任务时显示所有任务,而在主视图中将它们限制在给定项目中。