(转)Django ====> 实战学习篇六 改造Productlist界面 Django 的输入校验机制 实现输入校验

Django的验证有三层机制:

  1. 字段类型验证,除了应对数据库字段类型的Field类型外,还有EmailField, FileFIeld, URLField, PhoneNumberField, IPAdressField等等。
  2. 字段选项验证,如null=true, blank=true,choices editable, unique, unique_for_date等等。
  3. 表单验证,可以在Form中验证方法,可以针对所有表单做clean验证方法,也可以针对单项的验证方法:clean_xxx。

Product模型中,默认加入了不能为空,要求符合数字验证,还需要如下验证:

       1.验证price>0:需要在Form中验证;
       2. 验证title唯一:在Model中验证;
       3. 验证image_url的扩展名:在Form中验证,还可以顺便在Model中将其改为URLField类型。

实现输入校验:

  1. 在Model中修改字段参数值,防止重复输入标题,修改字段参数title中unique=True如下:
    from django.db import models  
      
    class Product(models.Model):  
        title = models.CharField(max_length=100,unique=True)  
        description = models.TextField()  
        image_url = models.URLField(max_length=200)  
        price = models.DecimalField(max_digits=8,decimal_places=2) 
  2. 继续修改字段类型,将image_url修改成字段类型URLField:见上边代码
  3. 限制price和输入的图片地址在form中修改: 
    depotapp/form.py
    
    #/usr/bin/python   
    #coding: utf8  
      
    from django import forms  
    from models import *  
    import itertools  
      
    def anyTrue(predicate, sequence):  
        return True in itertools.imap(predicate, sequence)  
    def endsWith(s, *endings):  
        return anyTrue(s.endswith, endings)  
      
    class ProductForm(forms.ModelForm):  
          
        class Meta:  
            model = Product      
      
        def __init__(self, *args, **kwargs):  
            super(ProductForm, self).__init__(*args, **kwargs)  
      
        def clean_price(self):  
            price = self.cleaned_data['price']  
            if price<=0:  
                raise forms.ValidationError("价格必须大于零")  
            return price  
        def clean_image_url(self):  
            url = self.cleaned_data['image_url']  
            if not endsWith(url, '.jpg', '.png', '.gif'):  
                raise forms.ValidationError('图片格式必须为jpg、png或gif')  
            return url  

ProductForm继承自ModelForm,可以根据model属性自动生成表单。

在生成的ProductForm上增加了clean_price和clean_image_url验证。结果如下:

     表单的展现如下:

creat_product.html

{% extends "base.html" %}  
  
{% block title %} 创建产品 {% endblock %}  
  
{% block content %}   
<table>  
<form action="" method="POST"> {% csrf_token %}  
  {{form}}  
  <tr>  
    <td colspan="2" align="right"><input type="submit" value="Create"/></td>  
  </tr>  
</form>  
</table>  
{% endblock %}  

    直接输出form对象{{form}}就会将表单格式化,而{%csrf_token%}作用是增加token表单项,避免重复提交。

####改造界面

将设计的内容全部复写到基础模板/depot/templates/base.html和专用模板/depot/templates/depotapp/list_product.html

base.html

<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
    <meta name="description" content="a depot implement with Django"/>  
    <meta name="keywords" content="django,depot" />  
    <meta name="author" content="Holbrook(http://hi.csdn.net/space-2668.html)" />  
    <title>{% block title %} 标题 {% endblock %}</title>  
    <link rel="stylesheet" href="/static/css/bootstrap.min.css">  
</head>  
<body>  
<div class="container">  
    {% block content %}   
    内容  
    {% endblock %}  
</div>  
</body>  
</html>  

list_product.html
{% extends "base.html" %}  
  
{% block title %} 产品清单 {% endblock %}  
  
{% block content %}   
<div class="container">     
    <div class="page-header">  
    <h2>产品清单</h2>  
</div>  
{% for item in list_items.object_list %}  
<div class="row" style="padding-top:10">  
    <div class="span3 media-grid">  
        <a href="#">  
        <img class="thumbnail" src="{{item.image_url}}" alt="">  
        </a>  
    </div>  
    <div class="span-two-thirds">  
        <h4>{{item.title}}</h4>  
        {{item.description}}  
    </div>  
    <div class="span2" style="align:right">  
        <p><a class="btn primary" href="{% url depotapp.views.view_product item.id %}">查看</a></a> </p>  
        <p><a class="btn success" href="{% url depotapp.views.edit_product item.id %}">编辑</a> </p>  
        <p><a class="btn danger" href="#">删除</a></p>  
    </div>  
</div>  
{% endfor %}  
{% if list_items.has_previous %}  
    <a href="?page={{ list_items.previous_page_number }}">上一页</a>  
{% endif %}  
  
<span class="current">  
    第{{ list_items.number }}页,共{{ list_items.paginator.num_pages }}页  
</span>  
  
{% if list_items.has_next %}  
        <a href="?page={{ list_items.next_page_number }}">下一页</a>  
{% endif %}  
<p>  
<a href="{% url depotapp.views.create_product %}">新增产品</a>  
</p>  
{% endblock %}  

这个模板继承自base.html 然后两个内容的实现

    注意其中链接方式的写法,href="{% url depotapp.views.view_product item.id %}"。这样定义的href是关联到view函数,而不是硬编码的URL。在以后如果改变了URLconf的定义,不需要再更改模板。

最后 填写表单 就可以访问了。

 

 

 

posted @ 2012-09-25 15:58  事件轮询,回不到过去  阅读(402)  评论(0编辑  收藏  举报