开发流程
- 立项。我们打算做一个TODO应用
- 大致规划,竞品分析,交互图(产品)。
- 技术选型。flask mongo数据库 bookstrap。
- 开始编码。先搭个架子。根据业务结构确定方法、类名、引用资源。
- 完成一个基础流程(展示列表)或先给假数据搭建静态页面或完成一个基础流程(get展示列表)
- 完成add, update,delete功能
- bookstrap美化
未完成的todo排到已完成的前面,未完成的里面创建时间早的排前面.
增加显示一列 todo列表的创建时间。
查询时格式化时间,不要毫秒。
from flask import Flask,url_for, redirect, render_template, request
import pymongo
from bson.objectid import ObjectId
from datetime import datetime
app = Flask(__name__)
# 数据库实例
content = pymongo.MongoClient('127.0.0.1', 27017)
db = content.todo
# mongo TODO文档结构
class Todo(object):
'''
一行待办事项数据结构。添加。
字段:事项内容,添加创建时间,状态(未完成、已完成),完成时间
'''
@staticmethod
def create_doc(self, content):
return {
'content': content,
'create_time': datetime.now(),
'status': 0, # 0未完成 1已完成
'finish_time': None
}
@app.route('/')
def index():
return redirect(url_for('get'))
@app.route('/get')
def get():
'''展示todo列表'''
# todo_list = db.todo.find({}).sort([('status',1), ('create_time',1)])
# print(todo_list)
todos = db.todo.find({}).sort([('status',1), ('create_time',1)]) # 返回迭代器,只能遍历一次,时间格式化最好在数据库查询语句中处理
todo_list2 = []
for todo in todos:
todo_list = {}
todo_list['_id'] = todo['_id']
todo_list['status'] = todo['status']
todo_list['content'] = todo['content']
todo_list['create_time'] = todo['create_time'].strftime('%Y-%m-%d %H:%M:%S')
todo_list2.append(todo_list)
return render_template('index.html', todo_list=todo_list2)
@app.route('/add', methods=['POST'])
def add():
'''添加一条todo'''
form = request.form
content = form['content']
print(content)
affected_id = db.todo.insert({
"content": content,
"create_time": datetime.now(),
"status": 0,
"finish_time": None
})
print(affected_id)
if affected_id:
return redirect(url_for('index'))
@app.route('/finish')
def finish():
'''更新状态已完成'''
args = request.args
_id = args['_id']
affect_id = db.todo.update(
{"_id": ObjectId(_id)},
{
"$set":{
"status": 1,
"finish_time": datetime.now()
}
}
)
print(affect_id)
return redirect(url_for('index'))
@app.route('/delete')
def delete():
'''删除无用的todo'''
args = request.args
_id = args['_id']
print(_id)
affected_id = db.todo.remove({
"_id": ObjectId(_id)
})
print(affected_id)
return redirect(url_for('index'))
if __name__ == '__main__':
app.run()
- base.html ↓
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<!-- bookstrap css js, jquery-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script src="https://cdn.bootcss.com/twitter-bookstrap/4.1.3/js/bookstrap.js"></script>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
- index.html ↓
{% extends 'base.html' %}
{% block title %}待办事项程序{% endblock %}
{% block content %}
<!-- 导航 -->
<div id="navigation" class="container">
<nav class="navbar navbar-default navbar-inverse">
<div class="navbar-header">
<a class="navbar-brand" href="#" ><span class="glyphicon glyphicon-th-list"></span>TODO</a>
</div>
</nav>
</div>
<!-- 添加todo表单 -->
<div id="todo-add " class="container">
<form action="{{ url_for('add') }}" method="post" class="form-inline" >
<textarea rows=5 cols=50 placeholder="请输入待办事项" name="content"></textarea>
<button type="submit" class="btn btn-success btn-lg" style="height: 50px;">添加</button>
</form>
</div>
<div class="divider"></div>
<!-- todo列表 -->
<div id="todo-list" class="container">
<table class="table table-striped">
<th>
<td>状态</td>
<td>创建时间</td>
<td>内容</td>
<td>删除</td>
<td>完成</td>
</th>
{% for todo in todo_list %}
<tr>
<td>{{ loop.index0 }}</td>
{% if todo.status == 0 %}
<td><span class="glyphicon glyphicon-asterisk btn-warning"></span></td>
{% elif todo.status == 1 %}
<td><span class="glyphicon glyphicon-asterisk btn-success"></span></td>
{% endif %}
<td>{{ todo.create_time }}</td>
<td>{{ todo.content }}</td>
<td><a href="{{ url_for('delete', _id=todo._id) }}"><span class="glyphicon glyphicon-remove"></span></a></td>
<td><a href="{{ url_for('finish', _id=todo._id) }}"><span class="glyphicon glyphicon-ok"></span></a></td>
{# {{ todo._id }} #}
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
效果如图:
遇到的问题
- 有关flask框架的报错。浏览器开发者工具中观察请求的url,观察后台日志url,print看有没有视图方法。看报错信息,看报错栈中自己的代码出错的那一行
- mongo根据objectId删除有问题,排查中。
- cdn,bootcss.com 提供的cdn有问题导致样式无法出来。解决 使用官方下载中提供的cdn
- push项目到码云时失败。一是要先关联远程和本地仓库。二是要输出正确码云密码,如果输入错误要先删除windows凭据。
- 关于时间的最佳设计,数据库冗杂,查询语言中格式化时间。
- 游标取值为迭代器,只能循环一遍。可以复制一份到普通变量中或再次查询(建议)。
7.content键报错没有键错误,经捡代码正确,原因数据库插入时某一行错误缺少content字段,导致查询时报错。 可以看出nosql数据库数据一致性不如关系型数据库。