元素中添加下述 HTML 超链接:
```
Add a New Category
```
### 检验结果
现在检验一下结果。启动或重启 Django 开发服务器,打开浏览器,访问 http://127.0.0.1:8000/rango/ 。点击新加的那个链接,跳转到添加分类页面,添加一个分类试试。下图是首页和添加分类页 面的截图。

图 7-1:通过表单添加一个分类
>分类不见了?
你添加的分类可能不会出现在首页,这是因为首页只显示最受欢迎的前 5 个分类。登录进入 管理界面可以看到全部分类。
确认分类成功添加的另一种方法是修改 rango/views.py 文件中的 add_category() 函数,把 form.save(commit=True) 改成 cat = form.save(commit=True),为通过表单创建的分类对象 提供一个引用,这样便可以在控制台中打印分类,例如 print(cat, cat.slug)。
### 清理表单数据
你或许还记得,Page 模型有个 url 属性,其类型为 URLField。在对应的 HTML 表单中,Django 期望这个字段中的文本是格式正确的完整 URL。然而,用户可能觉得输入 http://www.url.com 这样 的 URL 很麻烦,甚至根本不知道何为[正确的 URL 格式](https://support.google.com/webmasters/answer/76329?hl=zh-Hans "正确的 URL 格式")。
>URL 检查
多数现代浏览器会检查 URL 的格式是否正确,因此这里所说的情况只针对旧浏览器。虽然 如此,但是其中涉及如何在存入数据库之前清理数据。如果你没有旧浏览器做试验(或者你 不相信),可以把 URLField 更换成 CharField,这样渲染得到的 HTML 便不会指示浏览器做 检查,我们编写的清理代码就能执行。
为了防止用户输入的数据有错,我们可以在 ModelForm 子类中覆盖 clean() 方法。这个方法在数 据存为新模型实例之前调用,因此在这一时刻特别适合确认(甚至修正)用户在表单中输入的数 据。我们可以检查用户在 url 字段中输入的值是否以 http:// 开头,如果不是,在用户输入的值 前面加上 http:// 。
```
class PageForm(forms.ModelForm):
def clean(self):
cleaned_data=self.cleaned_data
url=cleaned_data.get('url')
# 如果 url 字段不为空,而且不以“http://”开头
# 在前面加上“http://”
if url and not url.startswith('http://'):
url='http://'+url
cleaned_data['url']=url
return cleaned_data
```
在 clean() 方法中,基本的处理过程是一样的,你可以轻易套用,按照自己的方式处理表单数 据。
➊ 表单数据从 cleaned_data 字典中获取。
➋ 要检查的表单字段使用字典的 .get() 方法从 cleaned_data 字典中获取。如果用户未在某个表单字段中输入值,那么 cleaned_data 字典中便没有对应的键值对。此时,.get() 方法返回 None,而不抛出 KeyError 异常。这样能让代码稍微简洁一点。
➌ 先检查要处理的表单字段中有没有值,如果有再检查值是什么。如果发现值不符合预期,那就做些处理,然后把新值存入 cleaned_data 字典。
➍ clean() 方法的最后必须返回 cleaned_data 字典的引用。否则改动不生效。
这个简单的示例展示了如何在保存之前清理数据。clean() 方法特别有用,尤其适合为字段提供 默认值,或者为用户没有填写的字段提供值。
覆盖 Django 框架的方法能为你的应用添加额外的功能。除了 ModelForm 类的 clean() 方法之 外,还有很多方法可以放心覆盖,详情参见 Django 文档。