Catalyst::Manual::Tutorial::09_AdvancedCRUD
学习笔记 (2010-8-28 星期六) -- 高阶 CRUD
文章来源:
......
Catalyst::Manual::Tutorial::09_AdvancedCRUD::09_FormFu 学习 |
本节内容来自:
概述
本节探索 ,用于管理表单,输入校验,通过数据库保存及回复数据。本章基于 HTML::FormFu 版本 0.05001。
HTML::FormFu 表单创建
从 Catalyst::Controller::HTML::FormFu 继承
首先, 修改文件 lib/MyApp/Controller/Books.pm
,改变继承关系,将如下:
BEGIN {extends 'Catalyst::Controller'; }
|
修改为:
BEGIN {extends 'Catalyst::Controller::HTML::FormFu'; }
|
记得修改 Makefile.PL :
requires 'Catalyst::Controller::HTML::FormFu';
|
添加 Action 用于显示和保存表单
编辑文件 lib/MyApp/Controller/Books.pm :
sub formfu_create :Chained('base') :PathPart('formfu_create') :Args(0) :FormConfig { my ($self, $c) = @_; my $form = $c->stash->{form}; if ($form->submitted_and_valid) { # 创建一本书 my $book = $c->model('DB::Book')->new_result({}); # 保存表单中该书信息 $form->model->update($book); # 为用户设置一条状态信息 $c->flash->{status_msg} = 'Book created'; # 返回书目列表页面 $c->response->redirect($c->uri_for($self->action_for('list'))); $c->detach; } else { # 从数据库获取作者信息 my @author_objs = $c->model("DB::Author")->all(); # 创建一个数组或数组引用,每个元素指向一个作者 my @authors; foreach (sort {$a->last_name cmp $b->last_name} @author_objs) { push(@authors, [$_->id, $_->last_name]); } # 从配置文件获取需要添加选择项的元素 my $select = $form->get_element({type => 'Select'}); # 将作者添加进去 $select->options(\@authors); } # 设置模板 $c->stash(template => 'books/formfu_create.tt2'); }
|
编写一个表单配置文件(Config File)
尽管 HTML::FormFu 支持 能识别的任意格式,但大多数人倾向于 YAML 格式。首先创建一个目录用于保存你的表单配置文件:
mkdir -p root/forms/books
|
创建文件 root/forms/books/formfu_create.yml :
--- # indicator is the field that is used to test for form submission indicator: submit # Start listing the form elements elements: # The first element will be a text field for the title - type: Text name: title label: Title # This is an optional 'mouse over' title pop-up attributes: title: Enter a book title here # Another text field for the numeric rating - type: Text name: rating label: Rating attributes: title: Enter a rating between 1 and 5 here
# Add a drop-down list for the author selection. Note that we will # dynamically fill in all the authors from the controller but we # could manually set items in the drop-list by adding this YAML code: # options: # - [ '1', 'Bastien' ] # - [ '2', 'Nasseh' ] - type: Select name: authors label: Author # The submit button - type: Submit name: submit value: Submit
|
注意: 从 perl 文档格式复制粘贴 YAML 文件比较麻烦。参考本章 这一小节,介绍了一个绝不会出错的配置文件格式。
更新 CSS 文件
编辑 root/static/css/main.css ,文件末尾添加:
... input { display: block; } select { display: block; } .submit { padding-top: .5em; display: block; }
|
这些设置用于垂直排列显示表单元素。注意现存的 .error 类的定义关联到色彩方案设置,这个设置是由 TTSite helper 生成的 root/lib/config/col 文件定义的。这样就有一个切入点可以控制 CSS 色彩设定。
创建一个模板页面用于显示表单:
编辑文件 root/src/books/formfu_create.tt2 :
[% META title = 'Create/Update Book' %] [%# Render the HTML::FormFu Form %] [% form %] <p><a href="[% c.uri_for(c.controller.action_for('list')) %]">Return to book list</a></p>
|
创建一个链接 for Create and Update via HTML::FormFu
编辑 root/src/books/list.tt2 ,在文件底部添加:
... <p> HTML::FormFu: <a href="[% c.uri_for(c.controller.action_for('formfu_create')) %]">Create</a> </p>
|
这样就在书目列表页面底部添加了一个新的链接,可以通过这个链接调用基于 HTML::FormFu 的表单。
测试 HTML::FormFu 添加书目的表单
使用 -r 参数启动服务:
$ script/myapp_server.pl -r
|
以用户 test01(密码:mypass)登录。进入书目列表页面后,点击表单底部的 HTML::FormFu "Create" 链接,输入以下内容:
Title: Internetworking with TCP/IP Vol. II Rating: 4 Author: Comer
|
点击提交按钮,然后返回到书目列表页面,你会看到 "Book created" 状态信息。
以上实现方式允许你输入任何乱七八糟的数据。尽管说我们通过下拉选择列表对作者一栏的录入进行了约束(其实对于侵略性的用户,依然可以通过"hacking"手段录入任何数值,这个防护并不严密),但是对于其他栏目并没有限制,比如标题栏没有限定长度(你甚至可以录入只有一个字母的书目),投票栏也没有限定类型(你可以输入数字,也可以输入非数字字符)。接下来的章节我们进行讨论。
注意: 依赖于你所使用的数据库,以及表中所建立的字段,数据库提供了一种直观的不同水平层级的数据 "类型约束"。前面章节一再强调了一个重要观点,web 应用程序本身不能进行任何数据校验。
HTML::FormFu 数据校验及过滤
虽说前面部分的 的示例演示了一种很好的自动创建表单的机制,但是这个模块的真正威力在于对用户输入数据的自动校验及过滤。校验约束可以保证用户输入适当的数据(比如说表单的 email 一栏就需要合法的 email 地址)。过滤机制可以滤掉输入信息中的空白字符,或者对元字符进行转义处理。
Add Constraints
编辑 root/forms/books/formfu_create.yml :
--- # indicator 域是用来测试表单提交 indicator: submit # 列出表单所有元素 elements: # 第一个元素是文本类型的 title 域 - type: Text name: title label: Title # 此项可选,定义鼠标滑过时的 title 提示信息 attributes: title: Enter a book title here # 添加此域的约束 constraints: # 定义长度必须为 5-40 个字符 - type: Length min: 5 max: 40 # 重新定义无效输入时的提示信息 message: Length must be between 5 and 40 characters # 定义一个文本域,用于输入 rating 数字 - type: Text name: rating label: Rating attributes: title: Enter a rating between 1 and 5 here # Use Filter to clean up the input data # Could use 'NonNumeric' below, but since Filters apply *before* # constraints, it would conflict with the 'Integer' constraint below. # So let's skip this and just use the constraint. #filter: # Remove everything except digits #- NonNumeric # Add constraints to the field constraints: # 确保输入为一个数字 - type: Integer message: "Required. Digits only, please." # 检查最大、最小值 - type: Range min: 1 max: 5 message: "Must be between 1 and 5." # 这里设定 author 选择列表,由于我们从 controller 直接获取 authors 列表添加进来 # 因此就不用手工添加如下 YAML 代码: # options: # - [ '1', 'Bastien' ] # - [ '2', 'Nasseh' ] - type: Select name: authors label: Author
# Convert the drop-down to a multi-select list
multiple: 1 # Display 3 entries (user can scroll to see others) size: 3 # One could argue we don't need to do filters or constraints for # a select list, but it's smart to do validation and sanity # checks on this data in case a user "hacks" the input # Add constraints to the field constraints: # Make sure it's a number - Integer
# The submit button - type: Submit name: submit value: Submit
# Global filters and constraints. constraints: # The user cannot leave any fields blank - Required # If not all fields are required, move the Required constraint to the # fields that are filter: # Remove whitespace at both ends - TrimEdges # Escape HTML characters for safety - HTMLEscape
|
狗日的服务器,本来这章还有 都写完了,编辑好的一大段文字都凭空消失了,不写了。
。。。。
阅读(1277) | 评论(0) | 转发(2) |