问题:
cppcms中form如何使用呢?官网上,除了教学篇-5之外,再无其他关于form使用的帮助文档了。当然,还有另外两种办法,就是看reference api文档和源代码。但是每次在使用form之前,或者长时间不用cppcms都使用后面两种办法自学的话,真是有点费劲费时。
小结:
基于上述问题原因,做了下面cppcms中form的小结,以便后续使用。
还是先看教学篇5的源代码,先看content.h。
#include <cppcms/view.h> #include <cppcms/form.h> namespace content { struct info_form : public cppcms::form { cppcms::widgets::text name; cppcms::widgets::radio sex; cppcms::widgets::select marital; cppcms::widgets::numeric<double> age; cppcms::widgets::submit submit; info_form(){ name.message("Your Name"); sex.message("Sex"); marital.message("Marital Status"); age.message("Your Age"); submit.value("Send"); add(name); add(sex); add(marital); add(age); add(submit); sex.add("Male", "male"); sex.add("Female", "female"); marital.add("Single", "single"); marital.add("Married", "married"); marital.add("Divorced", "divorced"); name.non_empty(); age.range(0, 120); } virtual bool validate(){ if(!form::validate()) return false; if(marital.selected_id()!="single" && age.value()<18){ marital.valid(false); return false; } return true; } }; struct message : public cppcms::base_content { std::string name, state, sex; double age; info_form info; }; }
照常例,使用cppcms时,都先准备content,同样我们定义一个message struct,template被填充message中的成员变量值。正如教学篇5中,页面只有一个简单的form,里面包含姓名(text)、性别(radio)、婚姻状况(select)、age(text),提交按钮(submit)五个form组件。
按照传统HTML页面来讲,当客户提交表单时,表单中信息均保存在http request中POST数组变量中。在cppcms中,我们可以通过使用http_request的post(std::string const &name)读取这些原始数据。以下,是我使用CPPCMS按照传统方式编写的一个简单表单交互测试。
1. 定义content.h
#ifndef CONTENT_H #define CONTENT_H #include <cppcms/view.h> #include <cppcms/form.h> namespace content { struct message : public cppcms::base_content { std::string name, state, sex; double age; };//end message }// end content #endif
2. 定义basicform view
<% c++ #include "content.h" %> <% skin form_skin %> <% view basicform uses content::message %> <% template render() %> <html> <body> <% if not empty name %> <h1>Hi, <%= name %></h1> <p>Your sex is <%= sex %>, and your marital status is <%= state %>. <p>Your age is <%= age %>.</p> <% else %> <h1> Input Your Details </h1> <form method="post" action=""> <p>Your name: <input type="text" name="name"></p> <p>Sex: <input type="radio" name="sex" value="male">Male <input type="radio" name="sex" value="female">Female</p> <p> Marital status: <select size="1" name="state"> <option value="single">Single</option> <option value="married">Married</option> <option value="divorced">Divorced</option> </select> </p> <p>Your age: <input type="text" name="age"></p> <p><input type="submit" value="Send"></p> </form> <% end %> </body> </html> <% end template %> <% end view %> <% end skin %>
3. 编写controller,base_form.cpp
#include <cppcms/application.h> #include <cppcms/applications_pool.h> #include <cppcms/service.h> #include <cppcms/http_request.h> #include <cppcms/http_response.h> #include <cppcms/url_dispatcher.h> #include <cppcms/url_mapper.h> #include <iostream> #include "content.h" using namespace std; class hello : public cppcms::application{ public: hello(cppcms::service &s):cppcms::application(s){} void main(std::string){ content::message c; if(request().request_method()=="POST"){ if(request().post("name")!=""){ c.name = request().post("name"); c.sex = request().post("sex"); c.state= request().post("state"); c.age = atoi(request().post("age").c_str()); render("basicform", c); } } else render("basicform", c); } }; int main(int argc, char **argv){ try{ cppcms::service app(argc, argv); app.applications_pool().mount(cppcms::applications_factory<hello>()); app.run(); } catch(std::exception const &e){ cerr<<e.what() << endl; } }
4. Makefile
CXX=g++ CPPCMSTMPL=cppcms_tmpl_cc LIBS=-lcppcms -lbooster all: clean hello_form hello_form: base_form.cpp basic_view.cpp content.h $(CXX) -Wall base_form.cpp basic_view.cpp -o hello_form ${LIBS} basic_view.cpp: base_form.tmpl content.h $(CPPCMSTMPL) base_form.tmpl -o basic_view.cpp clean: rm -rf hello_form basic_view.cpp
5. config.js
{ "service" : { "api" : "fastcgi", "ip" : "127.0.0.1", "port" : 9000 } }根据上述测试,不免有很多麻烦之处,比如在template中编写表单,在controller应用程序中,需要对表单的变量逐一进行解析。上述测试中,还没有加对表单数据的验证等。总之,编写起来比较繁琐。
不过,cppcms作者设计和实现了form的相关工具集用以解决传统表单交互的麻烦。
1. 在template中编写表单 —— 在cppcms template系统中定义了直接将form数据(model)转换成form视图(View)的构件(<% form as_p info %>),并且可以按照不同html_list_type方式形成不同类型的view.
2. 在content(model)中, 直接通过C++语言定义form表单,并且通过base_widgets类包包装了传统form的基础构件。其中新添加了numeric<T>组件,用以编制收集用户在表单输入数值,减少不必要的cast。另外,通过包装的widgets,还可以在此基础上,对用户录入数据进行验证。
3. widgets包装的每个form组件,都实现了load接口函数(纯虚函数,定义在base_form类中),这样用户只需要轻松调用load函数,实现request中表单数据的解析。
4. 通过form.h,即可看出cppcms眼中的form。一个form可以由多个sub-form组成,每个form都是由若干widget组成的。
因此,针对这样复杂的form,作者还提供了STL风格的form iterator,是不是很人性化啊。