Instead of doing this below in liquid when I might not even know all the possible colors that could exist, could I somehow just capture the full next row following "Color:" so that "Color:" is the triggertag that starts the capture and next row break is the trigger that decides when the capturing should stop?
And could I also use another word as the trigger of the end capture, for example if I know that I always want to capture what is between the only <strong> and </strong> tag in a description?
{% if product.description contains 'Color:' %}
{% if product.description contains 'Color: Red'%}{% assign TheColor = "Red" %}{% endif %}
{% if product.description contains 'Color: Yellow'%}{% assign TheColor = "Yellow" %}{% endif %}
{% if product.description contains 'Color: Ocean Blue'%}{% assign TheColor = "Ocean Blue" %}{% endif %}
{% if product.description contains 'Color: Light Blue'%}{% assign TheColor = "Ocean Blue" %}{% endif %}
{% if product.description contains 'Color: Blue'%}{% assign TheColor = "Blue" %}{% endif %}
{% if product.description contains 'Color: Black & white'%}{% assign TheColor = "Black & white" %}{% endif %}
{% endif %}
I've been googling for hours for something like this, I know I did it somehow in Asp Classic 10 years ago with a long code, but I figure it should be super simple in Liquid?
I don't have formal liquid education (which I probably share with many others who find this through searches) so a simple example in code rather than a "tech hint" or "clue" would be awesome.
Thank you!
Here's a bit of a hacky way to get just the colour, though it doesn't feel super reliable:
{% assign color = product.description | split: "Color: " %}
{{ color | last }}
This splits the description into an array. Everything before Color:is the first element, and everything after Color: is the second element. In our output we just print the second element.
This won't work right if there's anything else after the color declaration in your product description.
Related
I try to find out if my variable is an object or an array:
{% if variable is iterable %}It is an array{% else %}it is an object{% endif %}
But in cases I get the result:
It is an array
You are correct, the twig iterable test has shortcomings, since objects can be iterable as well. PHP has handy functions like is_array and is_object, however, it is not possible to access regular PHP function in Twig directly. So, we need to write a Twig extension/Test, i.e. add a new Twig_SimpleTest to check if an item is_array. You can add this test to your app configuration after the general twig bootstrap.
$isArray= new Twig_SimpleTest('array', function ($value) {
return is_array($value);
});
$twig->addTest($isArray);
and simply us it like this:
{% if var is array%} It is an array
{% else %} It is an object{% endif %}
The webapp2 i18n documentation has an example of specifying the locale in a parameter, e.g.:
www.example.com?locale=en_US
but Google search console says that this is not recommended.
I'd like to instead put the locale in the URL like this:
www.example.com
www.example.com/about
www.example.com/contact
www.example.com/fr
www.example.com/fr/about
www.example.com/fr/contact
What is a good way of setting up your webapp2 routes and passing the locale as a parameter to your handlers?
If you want to try the way I do it: Set a regex (app = webapp2.WSGIApplication([('/([^/]+)/?([^/]*)', RegionSearch)], config=settings.w2config, debug=settings.DEBUG) and then "pass on" the parameter to the template where you can set the locate arbitrarily for many different locales, timezones and currencies e.g.
{% if request.... == "..." %} # depend on values in the request
{% set currency = "SEK" %}
{% set format = "sv_SE" %}
{% set timezoneinfo = 'Europe/Stockholm' %}
{% set locale = "se" %}
{% endif %}
I ended up using a variation of Dj Dac's answer. I replace each route with two routes like this:
Route(r'/page', views.PageHandler),
Route(r'/<locale:\w\w>/page', views.PageHandler),
The route without the locale gives the default and is also used for the x-default hreflang tag.
Python3.4 Django1.9 Noob here... :)
I am trying to loop through a Django field but am not getting the desired results, here's the picture:
the models field "info" can hold strings and in some cases python lists. My issue in this case is when it's a list and I have to iterate through it...
e.g.:
say the "info" field has something like this: ['2016-02-23', '2016-03-01'] and I try to loop through it on the Django1.9 template like this:
{% for i in dates %} {{i}}<br /> {% endfor %}
I expect to see something like this:
2016-02-23
2016-03-01
instead I get this:
[
'
2
0
1
6
-
0
2
-
2
3
'
,
'
2
0
1
6
-
0
3
-
0
1
'
]
which makes me think the mySQL field holding the data is fooling me into thinking this is a python list... my ability to change the format of the database field are limited... any help would be appreciated!
models.py
class Events(....
info = models.CharField(max_length=150, blank=True)
views.py
dates_list = []
obj_dates = Events.objects.filter(id=id)
for i in obj_dates:
dates_list.append(i.info)
context = {"dates": dates_list)
Django 1.9 template
{% for i in dates %} {{i}} {% endfor %}
just looking at your code
obj_dates = Events.objects.filter(id=id)
is only going to get you one entry (as you are filtering by id) - you are returning a queryset with only one object.
When you use:
for i in obj_dates:
dates_list.append(i.info)
you are appending a string "['2016-02-23', '2016-03-01']"
to dates_list. That is to say that dates_list is just a list containing a single string - it appears to be a list containing a list but it is a list containing a string.
in python strings are iterable, so the template is iterating through one character in the string at a time, thus returning you
[
'
2
...
Solutions
A. The hacky way
dates_list.append(list(i.info))
that will convert that string "['2016-02-23', '2016-03-01']" into a list
B. a more django-ish approach
Ask yourself can you store dates in a better fashion that as text in a charfield?
One way to do it is to use a dateField then use m2m so you can store multiple dates.
class Events(models.Model)
info = models.CharField(max_length=150, blank=True)
dates = models.ManyToManyField(Dates, related_name='events', blank=True)
class Dates(models.Model)
date = models.DateField(auto_now=False, auto_now_add=False)
Thanks to luke_aus for the help!
I also found something that could work in some cases...
If you see yourself in a situation having to unpack or loop through a Python list stored in a CharField, try this... it worked very well in my case...
Views.py
import ast
date_list = []
for i in obj:
l = {
'dates': ast.literal_eval(i.info), # i.info is a CharField containing a python list
}
dates_list.append(l)
Template
{% for d in dates %}
{{d}}<br>
{% endfor %}
2016-02-23
2016-03-01
To deploy the ldap.conf with Ansible, I have to create one variable from an array, to use in a template ldap.conf.j2:
nss_base_group {{ ldap_base_group }}
The variable array:
---
ldap_groups: [ 'ORACLE', 'MY_SQL', 'POSTGR' ]
This has to result in one parameter, enhanced with al lot of static characters:
ldap_base_group:"dc=foo,dc=com?sub?(&(|(memberof:1.2.654.123456.1.5.2468:=cn=ORACLE,ou=Groups,dc=foo,dc=com)(memberof:1.2.654.123456.1.5.2468:=cn=MY_SQL,ou=Groups,dc=foo,dc=com)(memberof:1.2.654.123456.1.5.2468:=cn=POSTGR,ou=Groups,dc=foo,dc=com))(!(userAccountControl:1.2.654.123456.1.5.654:=2)))"
This is the same parameter made readable (not usable because of newlines, spaces etc):
ldap_base_group: "dc=foo,dc=com?sub?
(&
(|
(memberof:1.2.654.123456.1.5.2468:=cn=ORACLE,ou=Groups,dc=foo,dc=com)
(memberof:1.2.654.123456.1.5.2468:=cn=MY_SQL,ou=Groups,dc=foo,dc=com)
(memberof:1.2.654.123456.1.5.2468:=cn=POSTGR,ou=Groups,dc=foo,dc=com)
)
(!
(userAccountControl:1.2.654.123456.1.5.654:=2)
)
)"
Does anyone has found a nice solution to do this in Ansible? Maybe there is an other way to do this, I am eager to know alternatives too.
If you template this you should be able to do something along these lines:
ldap_base_group: "dc=foo,dc=com?sub?
(&
(|
{% for group in ldap_groups %}
(memberof:1.2.654.123456.1.5.2468:=cn={{ group }},ou=Groups,dc=foo,dc=com)
{% endfor %}
)
(!
(userAccountControl:1.2.654.123456.1.5.654:=2)
)
)"
If you need everything in a single line then just flattening this out should work fine.
I would like to know how can I perform this loop in Jinja :
for r,s in (v,t):
#Do something
When I try to write something similar in Jinja(Flask), I had an error :
ValueError: too many values to unpack
v and t are lists of dicts .
Found : In jinja I should use zipped
{% for s, t in zipped %}
#do something
{% endfor %}
where zipped = zip (s,t)