diff --git a/controller.go b/controller.go
index a6fbdd23..488ffcda 100644
--- a/controller.go
+++ b/controller.go
@@ -69,6 +69,7 @@ type Controller struct {
// template data
TplName string
+ ViewPath string
Layout string
LayoutSections map[string]string // the key is the section name and the value is the template name
TplPrefix string
@@ -213,7 +214,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
continue
}
buf.Reset()
- err = ExecuteTemplate(&buf, sectionTpl, c.Data)
+ err = ExecuteViewPathTemplate(&buf, sectionTpl, c.viewPath(), c.Data)
if err != nil {
return nil, err
}
@@ -222,7 +223,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
}
buf.Reset()
- ExecuteTemplate(&buf, c.Layout, c.Data)
+ ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath() ,c.Data)
}
return buf.Bytes(), err
}
@@ -248,9 +249,16 @@ func (c *Controller) renderTemplate() (bytes.Buffer, error) {
}
}
}
- BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...)
+ BuildTemplate(c.viewPath() , buildFiles...)
}
- return buf, ExecuteTemplate(&buf, c.TplName, c.Data)
+ return buf, ExecuteViewPathTemplate(&buf, c.TplName, c.viewPath(), c.Data)
+}
+
+func (c *Controller) viewPath() string {
+ if c.ViewPath == "" {
+ return BConfig.WebConfig.ViewsPath
+ }
+ return c.ViewPath
}
// Redirect sends the redirection response to url with status code.
diff --git a/controller_test.go b/controller_test.go
index 132971a1..c2025860 100644
--- a/controller_test.go
+++ b/controller_test.go
@@ -20,6 +20,8 @@ import (
"testing"
"github.com/astaxie/beego/context"
+ "os"
+ "path/filepath"
)
func TestGetInt(t *testing.T) {
@@ -121,3 +123,59 @@ func TestGetUint64(t *testing.T) {
t.Errorf("TestGetUint64 expect %v,get %T,%v", uint64(math.MaxUint64), val, val)
}
}
+
+func TestAdditionalViewPaths(t *testing.T) {
+ dir1 := "_beeTmp"
+ dir2 := "_beeTmp2"
+ defer os.RemoveAll(dir1)
+ defer os.RemoveAll(dir2)
+
+ dir1file := "file1.tpl"
+ dir2file := "file2.tpl"
+
+ genFile := func(dir string, name string, content string) {
+ os.MkdirAll(filepath.Dir(filepath.Join(dir, name)), 0777)
+ if f, err := os.Create(filepath.Join(dir, name)); err != nil {
+ t.Fatal(err)
+ } else {
+ defer f.Close()
+ f.WriteString(content)
+ f.Close()
+ }
+
+ }
+ genFile(dir1, dir1file, `
{{.Content}}
`)
+ genFile(dir2, dir2file, `{{.Content}}`)
+
+ AddViewPath(dir1)
+ AddViewPath(dir2)
+
+ ctrl := Controller{
+ TplName: "file1.tpl",
+ ViewPath: dir1,
+ }
+ ctrl.Data = map[interface{}]interface{}{
+ "Content": "value2",
+ }
+ if result, err := ctrl.RenderString(); err != nil {
+ t.Fatal(err)
+ } else {
+ if result != "value2
" {
+ t.Fatalf("TestAdditionalViewPaths expect %s got %s", "value2
", result)
+ }
+ }
+
+ func() {
+ ctrl.TplName = "file2.tpl"
+ defer func() {
+ if r := recover(); r == nil {
+ t.Fatal("TestAdditionalViewPaths expected error")
+ }
+ }()
+ ctrl.RenderString();
+ }()
+
+ ctrl.TplName = "file2.tpl"
+ ctrl.ViewPath = dir2
+ ctrl.RenderString();
+}
diff --git a/hooks.go b/hooks.go
index b5a5e6c5..528b58cc 100644
--- a/hooks.go
+++ b/hooks.go
@@ -72,7 +72,7 @@ func registerSession() error {
}
func registerTemplate() error {
- if err := BuildTemplate(BConfig.WebConfig.ViewsPath); err != nil {
+ if err := AddViewPath(BConfig.WebConfig.ViewsPath); err != nil {
if BConfig.RunMode == DEV {
logs.Warn(err)
}
diff --git a/template.go b/template.go
index 5415f5f0..d4d0ed12 100644
--- a/template.go
+++ b/template.go
@@ -32,8 +32,8 @@ import (
var (
beegoTplFuncMap = make(template.FuncMap)
- // beeTemplates caching map and supported template file extensions.
- beeTemplates = make(map[string]*template.Template)
+ // beeViewPathTemplates caching map and supported template file extensions.
+ beeViewPathTemplates = make(map[string]map[string]*template.Template)
templatesLock sync.RWMutex
// beeTemplateExt stores the template extension which will build
beeTemplateExt = []string{"tpl", "html"}
@@ -45,23 +45,30 @@ var (
// writing the output to wr.
// A template will be executed safely in parallel.
func ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
+ return ExecuteViewPathTemplate(wr,name, BConfig.WebConfig.ViewsPath, data)
+}
+
+func ExecuteViewPathTemplate(wr io.Writer, name string, viewPath string, data interface{}) error {
if BConfig.RunMode == DEV {
templatesLock.RLock()
defer templatesLock.RUnlock()
}
- if t, ok := beeTemplates[name]; ok {
- var err error
- if t.Lookup(name) != nil {
- err = t.ExecuteTemplate(wr, name, data)
- } else {
- err = t.Execute(wr, data)
+ if beeTemplates,ok := beeViewPathTemplates[viewPath]; ok {
+ if t, ok := beeTemplates[name]; ok {
+ var err error
+ if t.Lookup(name) != nil {
+ err = t.ExecuteTemplate(wr, name, data)
+ } else {
+ err = t.Execute(wr, data)
+ }
+ if err != nil {
+ logs.Trace("template Execute err:", err)
+ }
+ return err
}
- if err != nil {
- logs.Trace("template Execute err:", err)
- }
- return err
+ panic("can't find templatefile in the path:" + viewPath + "/" + name)
}
- panic("can't find templatefile in the path:" + name)
+ panic("Uknown view path:" + viewPath)
}
func init() {
@@ -149,6 +156,11 @@ func AddTemplateExt(ext string) {
beeTemplateExt = append(beeTemplateExt, ext)
}
+func AddViewPath(viewPath string) error {
+ beeViewPathTemplates[viewPath] = make(map[string]*template.Template)
+ return BuildTemplate(viewPath)
+}
+
// BuildTemplate will build all template files in a directory.
// it makes beego can render any template file in view directory.
func BuildTemplate(dir string, files ...string) error {
@@ -158,6 +170,10 @@ func BuildTemplate(dir string, files ...string) error {
}
return errors.New("dir open err")
}
+ beeTemplates,ok := beeViewPathTemplates[dir];
+ if !ok {
+ panic("Unknown view path: " + dir)
+ }
self := &templateFile{
root: dir,
files: make(map[string][]string),
diff --git a/template_test.go b/template_test.go
index 4f13736c..17690965 100644
--- a/template_test.go
+++ b/template_test.go
@@ -67,9 +67,10 @@ func TestTemplate(t *testing.T) {
f.Close()
}
}
- if err := BuildTemplate(dir); err != nil {
+ if err := AddViewPath(dir); err != nil {
t.Fatal(err)
}
+ beeTemplates := beeViewPathTemplates[dir]
if len(beeTemplates) != 3 {
t.Fatalf("should be 3 but got %v", len(beeTemplates))
}
@@ -103,6 +104,12 @@ var user = `
func TestRelativeTemplate(t *testing.T) {
dir := "_beeTmp"
+
+ //Just add dir to known viewPaths
+ if err := AddViewPath(dir); err != nil {
+ t.Fatal(err)
+ }
+
files := []string{
"easyui/public/menu.tpl",
"easyui/rbac/user.tpl",
@@ -126,6 +133,7 @@ func TestRelativeTemplate(t *testing.T) {
if err := BuildTemplate(dir, files[1]); err != nil {
t.Fatal(err)
}
+ beeTemplates := beeViewPathTemplates[dir]
if err := beeTemplates["easyui/rbac/user.tpl"].ExecuteTemplate(os.Stdout, "easyui/rbac/user.tpl", nil); err != nil {
t.Fatal(err)
}