Go template: calling method on $variable in template - templates

For some reason my template is not working, and I can't tell why. The value of . is a map[string]UpFile where UpFile is a struct with the method Path() which takes no arguments. Here is the relevant part of the template:
{{ range $key, $value := . }}
{{ $key }}
{{ end }}
The template works without the call to Path() on the variable $value. I've also tested the call to Path when the value of . was UpFile and it worked. The go doc on templates says calls to methods on variables is fine. The template compiles and is served however nothing in the range is outputted. When I omit the call to Path() I get a string of characters. Thanks for taking a look.
edit: Using a field from UpFile rather than the Path method provides expected output. Still don't understand why calling Path doesn't work.

The Path method is on the pointer receiver:
func (f *UpFile) Path() string { return f.path }
The value in $path is a Path. The method Path() cannot be called on a Path because pointer receiver methods are not in the value type's method set.
There are two ways to fix the problem. The first is to declare the method with a value receiver:
func (f UpFile) Path() string { return f.path }
The second way to fix the problem is to use *Path values instead of Path values. Change the map to:
var m map[string]*UpFile

Just omit the parentheses and it should be fine. Example:
{{ range $key, $value := . }}
{{ $key }}
{{ end }}

Related

Frozen-Flask, url_for() in Jinja2 and string concatenation during build

When running Flask normally, everything described below works absolutely fine.
When running a build in Frozen-Flask however, I run into the following issue:
In my Jinja2 template I tried this at first, where I'm having to create the route strings of many url_for() functions from multiple sources:
{% macro my_macro(foo) %}
Link text
{% endmacro %}
Although this runs fine in Flask, when I do a build with Frozen-Flask I get the following error:
werkzeug.routing.BuildError: Could not build url for endpoint 'index_'. Did you mean...
As you can see, the value of foo is missing.
So I thought that's annoying, but maybe the string concatenation of 'index_' ~ foo happens after the url_for() is parsed. So to test my theory, I tried this instead:
{% macro my_macro(foo) %}
{% set route = 'index_' ~ foo %}
Link text
{% endmacro %}
But I get the exact same error. Exactly. So, as if it's setting the value of set route before concatenating the value of the foo variable onto the end of 'index_', and passing that incomplete value through to url_for().
However, if I substitute foo for 'foo' (so now foo is a string not a variable) then the concatenation works fine. So I can't concatenate string with string variables in Frozen-Flask?
Is there any way around this or is this maybe a possible bug in Frozen-Flask?
Update: It appears to be an issue with data coming from routes.py where I have return render_template('my_template.html', foo='bar'). This foo variable, although it is being passed through to the base template where in turn it is passed through to the macro (it can be output to prove the data present and correct) this data however cannot, it seems, be used to dynamically create a route for use by url_for().
i think will help you a simple line code
Link Text
considering foo as string only will be concatenate, no with string1+strin2, only using html printing.

Template Namespacing

I have this line on one of my Service Providers:
\View::addNamespace('foo', asset('/bar'));
But doesn't render on my Blade template using the following line:
{{ HTML::image("foo::img.".$image, "Image") }}
Instead of rendering the above line, it displays a literal "foo::img.animagesomwwhereinmysite.png". Is there a way I can make this possible?
View::addNamespace only tells your Service Provider of the particular location where you are storing views; that declaration itself doesn't pass anything along to the view. (See the docs.)
So when you are calling the helper function {{ HTML::image() }}, it is expecting, as its first parameter, the URL of the image. In your case, you are specifying the URL as the literal string "foo::img.imagename".
Assuming your images are in the directory foo/img/, this should work:
{{ HTML::image("foo/img/".$image, "Image") }}

Go HTML templates: Can I stop the templates package inserting quotes around strings in scripts?

All of my templates have a variable indicating the root url of their associated images. I want to output that root before the filename of the image in the body of the template, but when I do so, the templates package attempts to put quotes around it. Here's a minimal piece of code that shows my problem. IMG_ROOT is an interface in this example to better simulate the real code. The script type is text/template because its contents will be used in an underscore.js template. The type doesn't appear to matter to how it's output though.
package main
import (
"html/template"
"os"
)
type Data struct {
IMG_ROOT interface{}
}
const tmpl = `
<body>
<script type="text/template">
<img src="{{.IMG_ROOT}}/file_name.jpg"></img>
</script>
</body>
`
func main() {
t, _ := template.New("").Parse(tmpl)
t.Execute( os.Stdout, &Data{ template.JSStr( "/path/to/file" ) } )
}
http://play.golang.org/p/wg9JK2w2lt
If I write <img src="{{.IMG_ROOT}}/file_name.jpg"></img>, I get "\/path\/to\/file/file_name.jpg" which isn't valid.
If I write <img src={{.IMG_ROOT}}/file_name.jpg></img>, I get "/path/to/file/"file_name.jpg which doesn't work either.
Is there a workaround for this? I've tried using every 'safe' type from the templates package for the IMG_ROOT type, but haven't had any luck. I could just write a function that concatenates and returns the root and file, but it seems like there should be a simpler solution.
Any ideas?
Thanks!
You could use printf built-in function:
<img src={{printf "%s/file_name.jpg" .IMG_ROOT}}></img>
http://play.golang.org/p/2v8Q6wHu0r
But instead, I would recommend creating a custom helper function and use it to create such paths:
const ImageRoot = "path/to/files/"
func StaticFile(filename string) string {
return ImageRoot + filename
}
func main() {
t, _ := template.New("").Funcs(template.FuncMap{"staticFile": StaticFile}).Parse(tmpl)
t.Execute(os.Stdout, nil)
}
And then in your templates you can just do
<img src="{{staticFile "image.jpg"}}"></img>
http://play.golang.org/p/NQTHmqNeT0
It's because html/template escapes things to prevent attacks, etc. I came to this question with a similar problem. Switching to text/template made my template behave as expected. That said, I'll just use another method to get the output I need and continue to use html/template.

How can I access part of a tuple which is returned from a custom tag in a Django template?

I have a function that returns a non-current user's first and last name as a tuple, using the following custom tag, where foo is a username from active directory:
{% name foo %}
I would like to access the first element of the tuple, and the only syntax I could think of is:
{{ {% name foo %}.0 }}
which is incorrect. How can I accomplish this?
You can't do that. If your tag is simply returning a value, there's no way to get the first part of it.
Instead, write an assignment tag, which sets a variable in the context. Then you can do this:
{% name foo as bar %}
{{ bar.0 }}

Django tag better way to resolve string with variable

I have a tag that has a variable that is a string with an embeded variable. Is there a better way to evaluate it than:
{% custom_extends "this_{{is.a.test}}" %}
-- backend
string_with_variable = "this_{{is.a.test}}"
result = Template(string_with_variable).render(context)
This works, but i wasn't sure if there was any lower level function that does the same.
I guess I'm a little dense this morning. Is the problem getting some_custom to accept a param that has an embedded variable reference in it? Or is it that you want the param to some_custom to be resolved before it is passed (which is a more general situation)?
If it's the latter case, checkout the Expr templatetag. With that you can do something like:
{% expr "this_"+is.a.test as some_string %}
{% some_custom some_string param %}
Update for comment:
Since this is for {% extends %}, which, as you correctly point out, needs to be the very first line in the file, simply set a variable in your view, e.g. my_custom_template = "this_"+is.a.test+".html" and pass it in with the context. Then in your template you can say {% custom_extends my_custom_template %} and you're good to go.
Of course, this assumes that your custom_extends tag does variable resolution like the normal extends tag does, but that's an easy thing to add to your code. See django/template/loader_tags.py, ExtendsNode.get_parent() for how the core code does it.
The answer is no. As of right now if you want to resolve/render a string you need to instantiate a Template and call render with your context.
result = Template("this_{{is.a.test}}").render(context)