天天看点

重拾cgi——页面模板

可能是因为公司里写代码用velocity习惯了,找了google的ctemplate来实现类似的功能。ctemplate相对velocity比较简单,只有变量替换,简单的引用、循环。这里有ctemplate的详细文档,相对来说,就是不能在模板上有太多的逻辑。

首先,前一篇里面贴了dispatcher,通过apache中设置环境变量,设置模板跟路径:

[cce lang=”cpp”]

ctemplate::template::settemplaterootdirectory(input.getenv(“template_path”));

[/cce]

然后,通过绑定的处理函数,调用真正的处理uri的函数后,将输出的dictionary对象,和模板合并:

std::string templatepath;

if(context.dict) //has dict

{

//get template

templatepath = context.dict->name() + ".tpl";

//expend

std::string out;

bool expandresult = ctemplate::expandtemplate(templatepath, ctemplate::strip_whitespace, context.dict.get(), &out);

if(expandresult) //good, we expend template success

context.ostream << cgicc::httphtmlheader();

context.ostream << out;

}

else //oops, we response 500

context.ostream << cgicc::httpstatusheader(500, "internal server error");

context.ostream << "fail to expand template: " << templatepath;

else

//如果没有字典,由对应的函数自己输出

这里是有字典输出的逻辑。获取根字典的名字,加上后缀,在根路径中查找对应的模板。然后调用ctemplate的函数,将模板展开。最后,将展开后的内容,通过流输出。

如果没有字典输出,默认当成处理函数中已经自己进行了输出(这里主要是为了让处理函数自己输出json内容)

另外一个分支,如果没有绑定,那么直接输出模板内容:

// find if there is a template

std::string templatepath = path.substr(1) + ".tpl";

if(ctemplate::mutable_default_template_cache()->loadtemplate(templatepath, ctemplate::strip_whitespace))

bool expandresult = ctemplate::expandtemplate(templatepath, ctemplate::strip_whitespace,

_emptydict.get(), &out);

else //not bind and not find a template file

context.ostream << cgicc::httpstatusheader(404, "not find");

context.ostream << "not find";

如果没有绑定,用一个空的字典,展开模板,也就是直接输出模板。如果这都没有找到,那么就返回404。

一个绑定函数的例子:

void handle(context &context)

std::vector<volume> volumes;

//fixme: mock数据

volume v1 ("1", "a", "cover_1.png", 5);

volume v2 ("2", "b", "cover_2.png", 1);

volumes.push_back(v1);

volumes.push_back(v2);

boost::shared_ptr<ctemplate::templatedictionary> listpagedict(new ctemplate::templatedictionary("list"));

for(int i = 0; i < volumes.size(); ++i)

ctemplate::templatedictionary *listsection = listpagedict->addsectiondictionary("list_sections");

listsection->setintvalue("id", volumes[i].id());

listsection->setvalue("name", volumes[i].name());

listsection->setvalue("cover_img_path", volumes[i].cover_path());

context.dict = listpagedict;

对应的模板文件:

[cce]

< !doctype html>

< html>

<head>

<meta charset="utf-8" />

<title>title</title>

</head>

<body>

<ol>

{{#list_sections}}

<li>name: {{name}}</li>

{{/list_sections}}

</ol>

</body>

< /html>

最后输出就是刚在volume对象的name字段。

转载自:https://coolex.info/blog/341.html