一、Django的表单(或类似表单)
表单是个综合性很大的标签,不管是前端还是后台,它都至关重要,它是由一系列组成的。
当然把form标签去掉,通过其他方法也能实现表单效果,就叫类表单吧。
参考:W3C:http://www.w3school.com.cn/tags/tag_form.asp
在Django中,它涉及面也很广,现在一块学学它。
参考:DjangoBook:http://djangobook.py3k.cn/2.0/chapter07/
二、表单步步为营
首先,定义好一系列表单的url、view、html等,如下:
1 Url: 2 #表单测试 3 urlpatterns +=patterns('', 4 (r'^test/$','login.views.test'),#表单入口 5 (r'^search/$','login.views.search'),#表单处理 6 )
html: form method="GET" action='/search/'> <input type="text" name='name'> <input type="text" name='age'> <input type="submit" value="Search"> </form>
其中,test视图函数仅仅是引用表单模板,真正处理表单提交的数据还是需要search视图函数。模板显示如下:
在这里我们要看看Django是怎么处理的,可能需要上一节的知识(点击链接:Django学习笔记(7):HttpRequest对象与HttpResponse对象)
这里可这样写search视图函数:
1 def search(request): 2 context={} 3 context=request.GET #一个字典对象,包括所有的 HTTP GET 参数 4 item=[] 5 for obj in context.items(): 6 item.append(obj) 7 return HttpResponse(item)
时刻记住上节学的知识,request对象。这里把上面提交的数据全部输出:显示如下:
(u'age', u'22')(u'name', u'BeginMan')
返回一个包含所有数据的(键、值)元祖的列表
有了上面的基础,那么对django处理表单似乎会更加理解了,go on!
三、一个简单的表单案例
from django.http import HttpResponse from django.shortcuts import render_to_response from mysite.books.models import Book def search(request): if 'q' in request.GET and request.GET['q']: q = request.GET['q'] books = Book.objects.filter(title__icontains=q) return render_to_response('search_results.html', {'books': books, 'query': q}) else: return HttpResponse('Please submit a search term.')
在HTML里我们定义了一个变量q。当提交表单时,变量q的值通过GET(method=”get”)附加在URL /search/上。处理/search/(search())的视图通过request.GET来获取q的值。
除了检查q是否存在于request.GET之外,我们还检查来reuqest.GET[‘q’]的值是否为空。
当然这是个健全的表单,改进的部分如下:
1 def search(request): 2 errors=[] 3 if 'q' in request.GET: 4 q = request.GET['q'] 5 if not q: 6 errors.append('输入不能为空') 7 elif len(q)>10: 8 errors.append('输入字符不能超过10个') 9 else: 10 news = New.objects.filter(title__icontains=q) 11 return render_to_response('test/test_search_results.html', 12 {'news': news, 'query': q}) 13 return render_to_response('test/form.html',{'errors':errors})
{% if errors %} <ul> {% for obj in errors %} <li style="color: red;">{{obj}}</li> {% endfor %} </ul> {% endif %} <form method="GET" action='/search/'> <input type="text" name='q'> <input type="submit" value="Search" class="btn btn-large btn-primary"> </form>
四、考虑使用Jquery Ajax实现表单处理
AJAX = 异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。
简短地说,在不重载整个网页的情况下,AJAX 通过后台加载数据,并在网页上进行显示。
jQuery load() 方法是简单但强大的 AJAX 方法。
load() 方法从服务器加载数据,并把返回的数据放入被选元素中。
jQuery get() 和 post() 方法用于通过 HTTP GET 或 POST 请求从服务器请求数据。
更多参考:http://www.w3school.com.cn/jquery/jquery_ajax_get_post.asp
继续我们的项目:
比如我有一个留言表,如下:
1 class Msg(models.Model): 2 """ 3 功能说明: 留言 4 --------------------------------- 5 Coder 时间 6 --------------------------------- 7 BeginMan 2013-04-26 8 """ 9 title = models.CharField(u'标题',max_length=30) 10 content = models.TextField(u'内容') 11 user = models.ForeignKey(User) 12 ip = models.IPAddressField(u'IP地址',blank=True) 13 datetime = models.DateTimeField(auto_now_add=True) 14 clickcount = models.IntegerField(u'点击数',default=0) 15 class Meta: 16 db_table = "Msg" 17 verbose_name = '留言反馈' 18 verbose_name_plural = '留言反馈' 19 def __unicode__(self): 20 return '用户[%s]发表的标题为"%s"的留言' %(self.user.username,self.title)
那么我想在留言列表页面要显示一个板块用来添加留言,这里使用jquery load()方法加载添加留言页面到留言列表页面上:
1 可以在base.html中这样写,其中css类add_msg是在列表页面预留的一个空板块,用来显示加载添加留言页面 2 $(document).ready(function(){ 3 $('.add_msg').load('/msg/send_msg/'); 4 })
我的留言板urls如下:
1 #留言板 2 urlpatterns += patterns('', 3 (r'^messages/message_list/$','login.msg.msg_list_page'), #留言列表 4 (r'^msg/detail/(?P<msg_id>\d+)/$','login.msg.msg_detail'),#留言详情 5 (r'^msg/send_msg/$','login.views.send_msg'),#发表留言 6 )
则在添加留言页面布局显示如下:
注意两个button:<button class="btn" onclick="_submit()">提 交</button><button class="btn" onclick="_reset()">重 置</button>
则js可写如下:
1 //导入jquery.min 2 <script type="text/javascript"> 3 //提交数据 4 function _submit(){ 5 var title=$('input[name="title"]').val(); 6 var content=$('textarea').val(); 7 if (title==""||content==""){ 8 return alert("输入的标题或内容不能为空!") 9 } 10 $.post('/msg/send_msg/',{"title":title,"content":content},function(){ 11 var alt=alert("添加成功!"); 12 if (!alt){ 13 $('input[name="title"]').val(""); 14 $('textarea').val(""); 15 window.location.href=window.location.href; 16 } 17 18 }) 19 } 20 //重置 21 function _reset(){ 22 $('input[name="title"]').val(""); 23 $('textarea').val(""); 24 }
那么剩下就开始写视图函数了,如下:
1 def send_msg(request): 2 context={} 3 try: 4 if request.method=="POST": 5 title=request.POST.get('title','') 6 content=request.POST.get('content','') 7 ip=request.META['REMOTE_ADDR'] #用户IP 8 if request.user.is_authenticated(): #判断用户是否已登录 9 user=request.user 10 else: 11 user=request.user #非登录用户将返回AnonymousUser对象 12 message=Msg.objects.create(title=title,content=content,user=user,ip=ip) 13 return HttpResponse('ok') 14 except Exception,e: 15 return HttpResponse('Error:%s' %e) 16 return render_template(request,'message/add_msg.html',context)
注意,这里重写了render_to_response(),取而代之的是render_template,可创建一个app,放置重写的代码,如下:
#coding=utf-8 from django.template import RequestContext from django.shortcuts import render_to_response def render_template(request, template_path, extra_context = {}): c = RequestContext(request) c.update(extra_context) return render_to_response(template_path, context_instance=c)
由于对未注册登录用户,不能发表留言,这里可在模板中通过{% if user.is_authenticated %}进行判定,稍微处理下,让表单呈现不可用状态,这点都是前端样式搞搞就行了,如:
五、关于验证
可以使用Javascript在客户端浏览器里对数据进行验证,要注意: 即使在客户端已经做了验证,但是服务器端仍必须再验证一次。 因为有些用户会将JavaScript关闭掉,并且还有一些怀有恶意的用户会尝试提交非法的数据来探测是否有可以攻击的机会。
前面的验证只是小部分,Django自带的验证在下节学习到。