Velocity array not working when array has empty values - arrays

I have the following code:
#set ($recsList = [$entity1,$entity2,entity3,entity4])
#foreach($article in $recsList)
<li>
Entity # $velocityCount in $article.id<br/>
</li>
#end
In my recsList only entity1 and 2 has a value, 3 and 4 are empty. Now, the above isn't working because entity3 and 4 in my recsList doesn't have a value. If I limit recsList to only entity1 and 2, then it is working just fine.
I've tried solving it by creating a new array only with products that has .id set:
#set ($displayRecs=[])
#foreach($article in $recsList)
#if($article.id!="")
$displayRecs.add($displayRecs.size(), $article)
#end
#end
But it still requires that recsList only contains the entity that has value listed.
Is there any way I can get it to work when having entity listed in recsList that doesn't have values?

You can use the quiet reference notation:
#set ($recsList = ["$!entity1","$!entity2","$!entity3","$!entity4"])
#foreach($article in $recsList)
<li>
Entity # $velocityCount in $article.id<br/>
</li>
#end
This way, missing values will appear as empty strings.

Related

Velocity Template : Display from nth position of an array

For customizing app dynamics email templates, we have to use velocity template 1.7
I have a health rule named ab-cd-ef-gh. First two part is constant and the last two part is the name of the microservice. I want to display the part after 'ef'. Please note that the length of the health rule is not fixed, meaning the part starting from 'ef' can have 2 part or 3 part or 5 part depending on the name.
I have used split function to split based on the delimiter '-'.
set ($output=$originalmessage.split('-'))
Output variable has all the parts of the health rule.
Now I want to print from 2nd index of the array, ie from 'ef' till the end of the array. To get the size of the array , i used #set ($outputsize=$output.size()), ie is array.size().
How will print the part starting from 'ef' till the end of the array.
The logic I used was as below.
#set ($start=5)
#foreach ($i in [$start..$outputsize])
${arrays.asList($output).get($i)}
But, I am not getting the output. Please help me to get the service name printed.
In VTL, arrays and lists are equivalent. On both of them you can use .get(i) or [i] to access the ith element, or call the .size() method.
So I guess that
#set ($outputsize = $output.size() - 1)
#set ($start=5)
#foreach ($i in [$start..$outputsize])
$output.get($i)
#end
is enough, as would:
#set ($outputsize = $output.size() - 1)
#set ($start=5)
#foreach ($i in [$start..$outputsize])
$output[$i]
#end

iterating through a Django model field produces unwanted format

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

Mongoid 4 update array attribute in a document

What is the mistake in this code for not be able to update an array within a document?
Model
class Foo
include Mongoid::Document
include Mongoid::Timestamps::Created
field :myarray, type: Array
end
Controller
def add_item
#foo = Foo.find_by(uuid: params[:uuid])
unless #foo.nil?
unless #foo.has_attribute? :myarray
#foo[:myarray] = Array.new
end
#foo[:myarray] << params[:item]
#foo.save
end
end
I am using Rails 4 with MongoId 4 and if I do p #foo before #foo.save I can see #foo correctly changed but for any reason the update is not persisted.
When you say this:
#foo[:myarray] << params[:item]
You're modifying the myarray array in-place so Mongoid probably won't recognize that it has changed. Then when you say #foo.save, Mongoid will look at #foo to see what has changed; but the array reference in #foo[:myarray] won't change so Mongoid will decide that nothing has changed and #foo.save won't do anything.
If you force a new array reference to be created by saying:
#foo[:myarray] += [ params[:item] ] # Or anything else that creates a whole new array
then Mongoid will notice that #foo[:myarray] has changed and #foo.save will send the change down to MongoDB via $set operation on the underlying document.
This looks like the Mongoid version of this ActiveRecord problem with PostgreSQL array columns:
New data not persisting to Rails array column on Postgres
The rule of thumb is "don't edit mutable values in-place, create whole new values instead: copy, edit, replace". That way you don't have to worry about manually managing the "is dirty" flags.

How to get length of (or count) of datastore entities through a reference collection definition in google datastore from client side

I have 1 to many datastore relationship between 2 Entities (google datastore) --- i.e. an instance in the Restaurant_Table can have many reviews from the Review_Table - as labeled by collection "restaurant_reviews"
As I spin through each restaurant (in a loop) to a list each of them in my template through jinja, I want to display the number or count of reviews there are for a single restaurant. All restaurants are passed from server in the form of a query from the datastore in variable restaurants as shown in the jinja2 logic in my template.
I'm getting an error that the query object TypeError: object of type 'Query' has no len(). Any other ideas on how to get the # of reviews for a single restaurant?? help!
{% for each in restaurants %}
<script>
var html_output = "";
var review_count ={{each.restaurant_reviews|length}};
...
{% endfor %}
DATASTORE ENTITY definition is:
class Review_Table(db.Model):
date_submission = db.DateTimeProperty(required=True, indexed=True)
course_id = db.ReferenceProperty(Restaurant_Table,
indexed=True, collection_name='restaurant_reviews')
To get the number of entities represented by the query you can use the count method:
db.Query(Kind).count()
You can't do this within a jinja template -- you would need to build your output in your handler, and then render to your template.
However, as the docs say the .count() method "is faster by a constant factor than actually retrieving all of the results, but the running time still scales linearly with the sum of offset + limit." Meaning, this could get really, really slow if you get a large number of restaurants/ reviews.
A better option, in my opinion, would be to add an extra property to your Restaurants model "num_reviews", which your handler would update every time a new review is added -- making very slightly more expensive/slower writes would become hugely cheaper/faster reads because no extra querying would have to be done.
Performance could be an issue, but this will accomplish the task:
var review_count = {% for n in restaurant_reviews %}{% if loop.index == 1 %}{{ loop.length }}{% endif %}{% endfor %};

Queries with JDOQL Unique Result Set

In my GAE application I want to make a JDOQL which returns a List where every element exist at most once even in the database there are more. How can I do this?
I dont know about JDOQL, but if you want a list where each entity exists utmost once i.e each list element is unique, then you could do the following:
Asume you have an entit type / model class that we call Type, with attributes att1,attr2.
You want to have a list of unique elements based on one or more of the attributes, say attr2.
you can use the following method that I adapted from a good source on the issue:
def unique(seq, idfun=None):
''' A function that returns a list of unique items in a very efficient manner
Refer to : http://www.peterbe.com/plog/uniqifiers-benchmark '''
# order preserving
if idfun is None:
def idfun(x): return x
seen = {}
result = []
for item in seq:
marker = idfun(item)
# in old Python versions:
# if seen.has_key(marker)
# but in new ones:
if marker in seen: continue
seen[marker] = 1
result.append(item)
return result
the to get a list of unique elements from the datastore type Type based on attr2 i could do something like:
list = Type.all()
unique_list = unique(list,lambda t: t.attr2)
Hope this helps because it has been the best method for me so far.

Resources