├── .gitignore
├── README.md
├── tags_xsrftoken.go
├── LICENSE
├── tags_urlfor.go
└── main.go
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 | *.test
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | beego-pongo2
2 | ============
3 |
4 | A tiny little helper for using Pongo2 with Beego.
5 |
6 | Documentation: http://godoc.org/github.com/oal/beego-pongo2
7 |
8 | ## Usage
9 |
10 | ```go
11 | package controllers
12 |
13 | import (
14 | "github.com/astaxie/beego"
15 | "github.com/oal/beego-pongo2"
16 | )
17 |
18 | type MainController struct {
19 | beego.Controller
20 | }
21 |
22 | func (this *MainController) Get() {
23 | pongo2.Render(this.Ctx, "page.html", pongo2.Context{
24 | "ints": []int{1, 2, 3, 4, 5},
25 | })
26 | }
27 | ```
--------------------------------------------------------------------------------
/tags_xsrftoken.go:
--------------------------------------------------------------------------------
1 | package pongo2
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/astaxie/beego"
7 | p2 "gopkg.in/flosch/pongo2.v3"
8 | )
9 |
10 | var xsrfTemplate = p2.Must(p2.FromString(``))
11 |
12 | type tagXSRFTokenNode struct{}
13 |
14 | func (node *tagXSRFTokenNode) Execute(ctx *p2.ExecutionContext, buffer *bytes.Buffer) *p2.Error {
15 | if !beego.BConfig.WebConfig.EnableXSRF {
16 | return nil
17 | }
18 |
19 | xsrftoken := ctx.Public["_xsrf"]
20 | err := xsrfTemplate.ExecuteWriter(p2.Context{"_xsrf": xsrftoken}, buffer)
21 | if err != nil {
22 | return err.(*p2.Error)
23 | }
24 | return nil
25 | }
26 |
27 | // tagXSRFParser implements a {% xsrftoken %} tag that inserts
28 | // just like Django's {% csrftoken %}. Note that we follow Beego's convention by using "XSRF" and not "CSRF".
29 | func tagXSRFParser(doc *p2.Parser, start *p2.Token, arguments *p2.Parser) (p2.INodeTag, *p2.Error) {
30 | return &tagXSRFTokenNode{}, nil
31 | }
32 |
33 | func init() {
34 | p2.RegisterTag("xsrftoken", tagXSRFParser)
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Olav Lindekleiv
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/tags_urlfor.go:
--------------------------------------------------------------------------------
1 | package pongo2
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/astaxie/beego"
7 | p2 "gopkg.in/flosch/pongo2.v3"
8 | )
9 |
10 | type tagURLForNode struct {
11 | objectEvaluators []p2.IEvaluator
12 | }
13 |
14 | func (node *tagURLForNode) Execute(ctx *p2.ExecutionContext, buffer *bytes.Buffer) *p2.Error {
15 | args := make([]string, len(node.objectEvaluators))
16 | for i, ev := range node.objectEvaluators {
17 | obj, err := ev.Evaluate(ctx)
18 | if err != nil {
19 | return err
20 | }
21 | args[i] = obj.String()
22 | }
23 |
24 | params := make([]interface{}, len(args)-1)
25 | for i := range params {
26 | params[i] = args[i+1]
27 | }
28 |
29 | url := beego.URLFor(args[0], params...)
30 |
31 | buffer.WriteString(url)
32 | return nil
33 | }
34 |
35 | // tagURLForParser implements a {% urlfor %} tag.
36 | //
37 | // urlfor takes one argument for the controller, as well as any number of key/value pairs for additional URL data.
38 | // Example: {% urlfor "UserController.View" ":slug" "oal" %}
39 | func tagURLForParser(doc *p2.Parser, start *p2.Token, arguments *p2.Parser) (p2.INodeTag, *p2.Error) {
40 | evals := []p2.IEvaluator{}
41 | for arguments.Remaining() > 0 {
42 | expr, err := arguments.ParseExpression()
43 | evals = append(evals, expr)
44 | if err != nil {
45 | return nil, err
46 | }
47 | }
48 |
49 | if (len(evals)-1)%2 != 0 {
50 | return nil, arguments.Error("URL takes one argument for the controller and any number of optional pairs of key/value pairs.", nil)
51 | }
52 |
53 | return &tagURLForNode{evals}, nil
54 | }
55 |
56 | func init() {
57 | p2.RegisterTag("urlfor", tagURLForParser)
58 | }
59 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | // A small library that lets you use Pongo2 with Beego
2 | //
3 | // When Render is called, it will populate the render context with Beego's flash messages.
4 | // You can also use {% urlfor "MyController.Action" ":key" "value" %} in your templates, and
5 | // it'll work just like `urlfor` would with `html/template`. It takes one controller argument and
6 | // zero or more key/value pairs to fill the URL.
7 | //
8 | package pongo2
9 |
10 | import (
11 | "net/url"
12 | "strings"
13 | "sync"
14 |
15 | "github.com/astaxie/beego"
16 | "github.com/astaxie/beego/context"
17 | p2 "gopkg.in/flosch/pongo2.v3"
18 | )
19 |
20 | type Context map[string]interface{}
21 |
22 | var templates = map[string]*p2.Template{}
23 | var mutex = &sync.RWMutex{}
24 |
25 | var devMode bool
26 |
27 | // Render takes a Beego context, template name and a Context (map[string]interface{}).
28 | // The template is parsed and cached, and gets executed into beegoCtx's ResponseWriter.
29 | //
30 | // Templates are looked up in `templates/` instead of Beego's default `views/` so that
31 | // Beego doesn't attempt to load and parse our templates with `html/template`.
32 | func Render(beegoCtx *context.Context, tmpl string, ctx Context) {
33 | mutex.RLock()
34 | template, ok := templates[tmpl]
35 | mutex.RUnlock()
36 |
37 | if !ok || devMode {
38 | var err error
39 | template, err = p2.FromFile(beego.BConfig.WebConfig.ViewsPath + "/" + tmpl)
40 | if err != nil {
41 | panic(err)
42 | }
43 | mutex.Lock()
44 | templates[tmpl] = template
45 | mutex.Unlock()
46 | }
47 |
48 | var pCtx p2.Context
49 | if ctx == nil {
50 | pCtx = p2.Context{}
51 | } else {
52 | pCtx = p2.Context(ctx)
53 | }
54 |
55 | if xsrf, ok := beegoCtx.GetSecureCookie(beego.BConfig.WebConfig.XSRFKey, "_xsrf"); ok {
56 | pCtx["_xsrf"] = xsrf
57 | }
58 |
59 | // Only override "flash" if it hasn't already been set in Context
60 | if _, ok := ctx["flash"]; !ok {
61 | if ctx == nil {
62 | ctx = Context{}
63 | }
64 | ctx["flash"] = readFlash(beegoCtx)
65 | }
66 |
67 | err := template.ExecuteWriter(pCtx, beegoCtx.ResponseWriter)
68 | if err != nil {
69 | panic(err)
70 | }
71 | }
72 |
73 | // readFlash is similar to beego.ReadFromRequest except that it takes a *context.Context instead
74 | // of a *beego.Controller, and returns a map[string]string directly instead of a Beego.FlashData
75 | // (which only has a Data field anyway).
76 | func readFlash(ctx *context.Context) map[string]string {
77 | data := map[string]string{}
78 | if cookie, err := ctx.Request.Cookie(beego.BConfig.WebConfig.FlashName); err == nil {
79 | v, _ := url.QueryUnescape(cookie.Value)
80 | vals := strings.Split(v, "\x00")
81 | for _, v := range vals {
82 | if len(v) > 0 {
83 | kv := strings.Split(v, "\x23"+beego.BConfig.WebConfig.FlashSeparator+"\x23")
84 | if len(kv) == 2 {
85 | data[kv[0]] = kv[1]
86 | }
87 | }
88 | }
89 | // read one time then delete it
90 | ctx.SetCookie(beego.BConfig.WebConfig.FlashName, "", -1, "/")
91 | }
92 | return data
93 | }
94 |
95 | func init() {
96 | devMode = beego.AppConfig.String("runmode") == "dev"
97 | beego.BConfig.WebConfig.AutoRender = false
98 | }
99 |
--------------------------------------------------------------------------------