这次我们来实现一下对已经发表的Todo进行修改和删除。
我们先改变一下模型的save方法,使它有两种功能,对于不存在于数据文件的数据进行新增,对于已经存在的进行更新,代码如下。
def save(self):
"""
新建数据或修改数据
"""
if self.id == -1:
# 数据是新数据
global next_id
self.id = next_id
next_id += 1
with open(self.get_db_path(), 'a') as f:
data_str = json.dumps(self.__dict__)
f.write(data_str + '\n')
else:
obj_list = self.all()
with open(self.get_db_path(), 'w') as f:
for obj in obj_list:
if obj.id == self.id:
data_str = json.dumps(self.__dict__)
else:
data_str = json.dumps(obj.__dict__)
f.write(data_str + '\n')
再增加一个delete方法。
@classmethod
def delete(cls, id):
obj_list = cls.all()
with open(cls.get_db_path(), 'w') as f:
for obj in obj_list:
if obj.id == id:
continue
else:
data_str = json.dumps(obj.__dict__)
f.write(data_str + '\n')
然后我们现在就需要写update和delete路由函数了。我们需要在首页的HTML文件里增加对应于每个Todo的修改和删除按钮,由于它们每个都是对应的URL都是动态的,所以依旧需要我们按之前的replace方法来替换动态字符串,比较麻烦,所以我们使用以Jinja2模版来实现一下。具体的template函数和前台请看完整代码,这里不再赘述。
@login_required
def delete(request):
data = request.form()
obj_id = data.get('id', -1)
Todo.delete(int(obj_id))
return get_headers(code=302, location='/') + '\r\n'
@login_required
def update(request):
if request.method == 'GET':
id = request.form().get('id', -1)
todo = Todo.get_by(id=int(id))
body = template('update.html', id=id, title=todo.title)
return get_headers() + body + '\r\n'
elif request.method == 'POST':
data = request.form()
obj_id = data.get('id', -1)
# 这里id是整型
todo = Todo.get_by(id=int(obj_id))
todo.title = data['title']
todo.save()
return get_headers(code=302, Location='/') + '\r\n'
else:
return error(request)
下面我们还需要实现一个很重要的功能,那就是权限,只有自己创建的Todo才可以删除。我们继续用装饰器实现。
def owner_required(f):
def decorator(request):
user = current_user(request)
id = request.form().get('id', -1)
obj = Todo.get_by(id=int(id))
if obj.user_id == user.id:
return f(request)
else:
return get_headers(code=302, Location='/login') + '\r\n'
return decorator
然后给delete函数和update函数加上owner_required就好了。
我们这次完成了Todo的修改和删除以及权限的控制,还使用了Jinja2模版渲染了前端页面。
完整代码:https://github.com/KEYYYYY/simple-server