提交表单及发表文章
提交表单
1. html表单
<form method="POST" action=""> {% csrf_token %}
<input type="text" name="title" />
<textarea name="content"></textarea>
<button type="submit">发表</button>
</form>
- input 标签 自开自闭
- textarea 标签 多行文本框 有开闭标签
- submit 按钮 html表单 一定要有一个submit按钮
- {% csrf_token %} 一定要写在form后面
2. 后台处理
if request.method == "GET":
return render_to_response("xxx.html",
{},
context_instance=RequestContext(request))
else:
title = request.POST["title"].strip()
content = request.POST["content"].strip()
# do anything
csrf 跨站请求伪造
- A为可信站点,B为危险站点。
- 在A登录后,没有退出,然后访问B网站。
- B网站伪造了一个表单,从用户的浏览器提交到A网站。提交到A网站的请求,浏览器会自动带上认证信息,结果A网站认证通过。
- 如果这个请求是修改密码,用户的账号就被盗了。
Django 防止CSRF
- 给form表单添加一个隐藏字段,一个每个浏览器都不一样的随机码。
- 后端验证随机码是否存在。
- 危险网站无法提前探知随机码,也就无法伪造请求了。
- {% csrf_token %}
什么是context(环境)
context_instance = RequestContext(request)
- 没有来之前就已经存在的东西就是环境
- 模板中不用定义就可以使用的变量就是环境
- render_to_response 的第二个参数,那个字典,就是环境。
- RequestContext(request) 是由请求对象提供的环境,提供了一些模板可以使用的变量,这些变量是从请求中解析出来的。csrf_token 就在其中。
- from django.template import RequestContext
位置参数与关键字参数
- do_something(1) 位置参数
- do_something(in=1, out=2) 关键字参数
- do_something(1, out=2) 位置参数在前,关键字参数在后
- def do_anything(*args, **kwargs): pass
- args 是位置参数集合,是列表,*解列表为位置参数
- kwargs 是关键字参数集合,是字典, ** 是解字典为关键字参数
uls 与 reverse
{% url 'URL名称' 位置参数 关键字参数=值 %}
reverse('URL名称', args=[位置参数], kwargs={关键字参数})
- 作用相同
- url用于模板中,html中。
- reverse 用于控制器中,python中。
- 他们得到的返回值都是一样的,都是字符串,就是解析出来的url。
消息组件
from django.contrib import messages
添加消息( 消息级别:DEBUG, INFO, SUCCESS, WARNING, ERROR)
message.add_message(request, messages.ERROR, u'标题和内容不能为空')
...
context_instance=RequestContext(request)
消息展示
{% if messages %}
{% for message in messages %}
<div class="alert alert-info"> {{ message }} </div>
{% endfor %}
{% endif %}
- 消息只展示一次。
- 给request变量增加了消息属性。
- message增加在这个请求上面,然后这个请求包装成一个请求环境,传给了模板,所以模板上就有了这个消息。
- message实际上是存在数据库中。在任何地方添加消息之后,如果你一直不输出,一直不在模板上展示这个消息,让这个消息一直存着,就算是这个请求返回之后,这个消息也不丢失,直到有一次,页面里面传入了请求的环境,然后再页面里面展示了消息,这些消息就会被展示出来(包括以前没有展示的)。
帖子详情页面
- 数据模型:已定义
- URL:/article/detail/<article_id>
- 控制器:展示一个页面
- 模板:继承与base.html,用bootstrap美化,展示必要信息
作业
- 文章列表页面,增加“发表文章”的按钮
- 增加发表文章的页面及功能
- 发表成功/失败有消息提示
- 文章列表页面,文章的标题为链接,可点击,点击跳转到文章详情
- 完成文章详情
/article/views.py 注意的代码
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.contrib.auth.models import User
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
def create_article(request, block_id):
block_id = int(block_id)
block = Block.objects.get(id=block_id)
if request.method == "GET":
return render_to_response("article_create.html", {"b": block},
context_instance=RequestContext(request))
else: # request.method == "POST"
title = request.POST["title"].strip()
content = request.POST["content"].strip()
if not title or not content:
messages.add_message(request, messages.ERROR, u"标题和内容均不能为空")
return render_to_response("article_create.html",
{"b": block, "title": title, "content": content},
context_constance=RequestContext(request))
owner = User.objects.all()[0] # TODO:
new_article = Article(block=block, owner=owner, title=title, content=content)
new_article.save()
messages.add_message(request, messages.INFO, u'成功发布文章')
return redirect(reverse("article_list", args=[block.id]))
注意:python str.format()格式化中文
import sys
reload(sys) # 如果没法直接调用setdefaultencoding()方法就加上这句
sys.setdefaultencoding('utf-8')