Issues linking data in Flask / MongoDB - python

New to the whole coding thing, currently doing a course in Python/Flask and giving it my best shot.
I have a MongoDB Atlas DB, with 2 collections in it for drinks.
The structure looks like the below. The values in the array are the _id values of the ingredients in another collection.
_id:5e0f54d31c9d44000015483f
drinkName:"Margarita"
Ingredients:["5e13274e1c9d440000490ed8","5e1327571c9d440000490ed9","5e1327621c9d440000490eda","5e13276b1c9d440000490edb"]
And another collection with the below
_id:5e1327261c9d440000490ed7
ingredientName:"Slice Lemon"
My problem is I'm trying to render the results of the array in Flask on a page. But I can't seem to look up the object id's in the ingredients table, and display the ingredientName of the object.
I can display the array fine, but can't then go to the ingredients collection to get the name.
This is what I have in the html
{% for ingredient in drink.ingredientList %}
{% for ing in ingredients %}
{% if ing._id == ingredient %}
<li>
{{ ing.ingredientName }}
</li>
{% endif %}
{% endfor %}
{% endfor %}
Any help on this would be greatly appreciated, because I feel like I'm banging my head against the wall at this point.

Related

trying to show elements of a dictonary that's stored in django model

What i have is a django project that stores a dictionary in a json model.
class MyModel(models.Model):
jsonM = JSONField()
The dictionary is just a bunch of numbers. known as my sortedList
I am accessing these numbers in my html by passing then as a context variable in my views.py
numbers_in_sortedList = MyModel.objects.all()
return render(
request,
"showdata.html",
context={'numbers_in_sortedList':numbers_in_sortedList },
)
I am able to show the dictionary on my html via:
<li>
{% for number in numbers_in_sortedList %}
{{item.jsonM}}
{% endfor %}
</li>
this works find and shows 1 bullet point, with all the values in a dictionary.
however how can i access each individual element in the dictionary individually?
I have tried nesting a for loop but it doesn't seem to work, stating that "myModel object is not iterable"
<li>
{% for number in numbers_in_sortedList %}
{% for item in number %}
{{item.jsonM}}
{% endfor %}
{% endfor %}
</li>
Any ideas?

Dealing with json type data in a template

I am after some advice. I know what I need to do, but not sure how I can do it
I send data to a template that comes from from a database
Let's say the database has two fields
Field one (name)
Name of a person
Field two some json (the json has a structure like this, with many field:value)
{
"field1":"value1",
"field2":"value2"
}
I can output this as
Field one (name) Field two (json)
What I actually want to do though, is loop through the json, and print out the values, so like this
Name of a person field1|field2
I am a bit lost on how I can do that
I tried something like this
{% for anitem in fieldtwo %}
<div>{{ anitem }}</div>
{% endfor %}
But that just seems to print out each character
Is what I need to do achievable? I am thinking I just have the whole approach wrong
Thanks
Grant
In the end, I ended up using another dictionary and then pass that through to the template
I loop through the queryset in the view to populate the dictionary
In the template I then did this (alloweddomains is from the view)
{% for testcaseid, domains in alloweddomains.items %}
{% if listtestcase.id == testcaseid %}
{% for key, value in domains.items %}
<div><a class="sendtolinkdisabled" data-testcasename="{{ listtestcase.name }}" data-testcaseid="{{ $
{% endfor %}
{% endif %}
{% endfor %}
This basically looped through the dictionary and if there was a match to my unique ID I get the data and do something with it
I tried various ways to not need the if statement and just get the right point in the dictionary, but nothing seemed to work (so I took the if approach)
Grant

Jinja List Issue

I am getting a weird problem in Jinja, I have a list endpoints, which contains dictionary for every endpoint. In each dictionary, there is a key tags which is a list. Every item in tags is itself a dictionary where the key value gives the label of a tag. endpoint may have similar tags.
A sample abstract representation of an endpoints object can be:
[ {"tags":[{"value":"car"},{"value":"place"}]} , {"tags":[{"value":"van"},{"value":"place"}]} ]
what I want is to simple display unique tags in a div. It is simple, keeping a list of all displayed tags and upon getting a tag, checking if it is already in the list, and if not display it and add it to the list. Weirdly, it's not working.
The codes are:
{% set tagValues = [] %}
{% for endpoint in endpoints %}
{% for tag in endpoint["tags"]%}
{% set tagValue = tag["tag"]["value"] %}
{% if tagValue not in tagValues %}
{% set tagValues = tagValues + [tagValue] %}
<span >{{ tagValue }}</span></a>
{% endif %}
{% endfor %}
{% endfor %}
it is not working, for example, for the enpoints list above, I am getting the following output:
car place van place
is there any problem with the codes ?
I recommend creating a distinct list of tags in your View. e.g.
distinctTags = list(set([tag for endpoint in endpoints for tag in endpoint]))
and passing that to your template
{% for tag in distinctTags %}
<span >{{ tagValue }}</span></a>
{% endfor %}
this has the advantage of the distinct tag code being reusable and the code being less procedural.
my jinja knowledge is limited, but by adding tagValues to the output, it appears that it's reset after each iteration of the outer loop. I'd guess it's to do with scopes, but don't know.
My recommendation would be to pre-process your endpoints in regular python before passing to jinja

Grouping of search results in a django template

I have a search results page in django. The results list a video title, video description and some meta data. It also includes the topic the video is in.
Instead of returning a full list of videos, I would like to try grouping my results by topic. Then, within each group, only show the top 1-3, with a link to "view all x videos in y topic" The determining factor of whether to show 1, 2, or 3 in the group would be a calculation based on the total number. So if there are under 10, only show 1 video in that grouping. If there are between 10-30 in the group, show 2 videos. If 30 or more in that grouping, show 3. (Determining 1-3 might not be necessary, I would be ok doing top 3)
My code is currently pretty simple to just return results. But I can't figure out how to get the groupings set up within django's template language. I guess I could do this in my view but hoping there's some simple filters I'm not aware of to help and do it in the template. Thanks for any advice.. Here's my current code:
<h4>Search Results</h4>
<p>{{ res.hits.total }} matches found for <span id="qresult">{% if q %}'{{ q }}'{% else %}all{% endif %}</span></p>
</div>
<ul class="search-list" id="search-results">
{% if res.hits.total > 0 %}
{% for h in reshh %}
{% with h|get_underscore_value:"_source" as source %}
<li><a href='/video/{{ source.slug }}'>{{ source.title }}</a>
<p>{{ source.description }}</p>
<span class="sr-meta" style="">metadata</span>
<p>(topic: {{ source.topic_name }})</p></li>
{% endwith %}
{% endfor %}
{% endif %}
</ul>
btw it's pulling from elasticsearch. res.hits.hits._source is where my results are contained. The "get_underscore_value" is just a custom filter to get around django complaining that my variable begins with an underscore...
Check out the regroup templatetag: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#regroup

sort in jinja2 when attribute is not available

I have a set of articles (using pelican for generating static sites) which includes a category called hotels. I'd like to sort these hotels. The problem is that only the hotels have an attribute called 'city' while the other articles do not and this obviously leads to the following error:
Caught exception "'pelican.contents.Article object' has no attribute 'city'".
Here is the code I am using:
{% for article in articles|sort(attribute='city') %}
{% if article.category == 'hotels' %}
<a href="hotels/{{ article.slug }}.html">
<p>{{ article.title }}</p>
</a>
{% endif %}
{% endfor %}
Is there a way to check to see if the attribute exists and provide some default value so that it does not cause an error?
You may be able to move your if statement into your for loop as a filter:
for article in articles if article.category == 'hotels' | sort(attribute='city')
If you want to show only entries that have a 'city' attribute, and have that list sorted by 'city', do:
for article in articles|selectattr("city")|sort(attribute="city")
If you want to iterate over only the hotels, see Sean Vieira's answer. If you want to iterate over all articles, but have the hotels sorted while the rest are in arbitrary order, you can do it by using macros:
{% macro my_macro(article) %}
...
{% endmacro %}
{% for a in articles if a.category == 'hotels' | sort(attribute='city') %}
{{ my_macro(a) }}
{% endfor %}
{% for a in articles if a.category != 'hotels' %}
{{ my_macro(a) }}
{% endfor %}
This will include everything you defined in my_macro first for each hotel, in the desired order, then for each article that is not a hotel.
I found this page when was looking for a similar solution.
Eventually, I solved it a bit differently and it might be helpful for someone else.
In one of my templates for Pelican I added statistics collected by 'post_stats' plugin about approximate time to read. It looked like
~{{ article.stats['read_mins']|default("0") }} min read
But if the plugin is not loaded then the 'article' object doesn't have the 'stats' attribute and rendering fails.
Jinja has the builtin test for testing if a variable is defined.
So, I came up with this solution
~{{ article.stats['read_mins'] if article.stats is defined else "0" }} min read

Categories