Iterating Through Many to Many Model - html

I have a model like so:
`class task(models.Model):
name = models.CharField(max_length=100)
notes = models.TextField()
created = models.DateTimeField()
created_by = models.ForeignKey(User)
subtask = models.ManyToManyField('self')
`
I'm having trouble writing out the view for it, essentially
<li>task #1</li>
<li>subtask#1.1</li>
<li>subtask#1.2</li>
<li>task #2</li>
<li>subtask#2.1</li>
<li>subtask#2.2</li>
.
.
.
.
I tried creating a for loop to iterate through them using but it doesn't show up nested like how I would want it
{% for task in items %}
<li>{{ task.name }}</li>
{% for subtask in task %}
<li>{{ subtask.name }}</li>
{% endfor %}
{% endfor %}

This is an HTML issue rather than with your django code
{% for task in items %}
<li>{{ task.name }}
<ul>
{% for subtask in task.subtask.all %}
<li>{{ subtask.name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}

Related

Display language filtered posts by category in Jekyll

I run a Jekyll blog in multiple languages using the setup making Jekyll multilingual by Sylvain Durand without use of any plugin.
All posts have the following markup:
---
title: Hello world!
lang: en
ref: hello
---
The posts are using the normal folder structure:
jekyll
|
-- posts
|
--name-of-post
--name-of-post-2
--name-of-post-3
I have a page named en.md which have layout: home and lang: en markup, which displays English posts correctly with the following code in home.html
{% assign posts=site.posts | where:"lang", page.lang %}
<ul>
{% for post in posts %}
<li>
{{ post.title }}
</li>
{% endfor %}
</ul>
But I would like instead to display posts by category, filtered on the language.
Tried to achieve this with the following:
{% assign posts=site.categories | where:"lang", page.lang %}
<div class="categories">
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
</div>
When I build, the following message is displayed
Liquid Exception: no implicit conversion of String into Integer in /_layouts/home.html
Tried many variants, but none seems to work.
This does the trick :
---
Title: English posts
lang: en
---
<ul>
{% for category in site.categories %}
{% comment %}
Here we have something like this
category = Array[
"category1",
[doc1, doc2]
]
{% endcomment %}
{% assign name = category[0] %}
{% assign posts = category[1] %}
{% comment %}
>> This also works
{% assign name = category.first %}
{% assign posts = category.last %}
{% endcomment %}
{% comment %}
>> Filtering posts based on their `lang` variable
>> and on the current `page.lang`
{% endcomment %}
{% assign selectedPosts = posts | where:"lang", page.lang %}
{% comment %}
>> Let's make sure that we need to print something
{% endcomment %}
{% if selectedPosts.size > 0 %}
<li>
Category {{ name }} :
<ul>
{% for post in selectedPosts %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
Short version :
<ul class="post-list">
{% for c in site.categories %}
{% assign selectedPosts = c.last | where:"lang", page.lang %}
{% if selectedPosts.size > 0 %}
<li>Category {{ c.first }} :
<ul>
{% for post in selectedPosts %}
<li>{{ post.title }} - {{ post.lang }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
WITH the built-in category solution of Jekyll
I found this partial solution, just like you did...:
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
What you want to do/did is filter the 'posts' variable with the page language. This can indeed be done with assign using a where filter, but should look like this (as 'lang' is a attribute of the individual post and not of the category):
{% assign lang_posts = posts | where:"lang", page.lang %}
This leads to the following code:
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% assign lang_posts = posts | where:"lang", page.lang %}
{% for post in lang_posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
WITHOUT the built-in category solution of Jekyll
If you have a random list of categories in your front matter, like this:
- categories:
- web
- css
- internet
... and your sites _config.yml contains a similar (but more complete) list, like this:
- categories:
- web
- css
- internet
- html5
- jekyll
You have a whole other problem. In that case you are NOT using the built-in category solution of Jekyll and this solution does not apply. A lot of the statements mean different things in that case, like this:
{% for category in site.categories %}
{{ category | first }}
It means you loop over all existing categories from the _config.yml, and category | first should then be category. In this situation you probably want something like this:
<ul class="categories">
{% for category in site.categories %}
<li><a name="{{ category }}">{{ category }}</a>
<ul>
{% assign posts=site.posts | where:"lang", page.lang %}
{% for post in posts %}
{% if post.categories contains category %}
<li>{{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Note that this is just simple Jekyll/liquid array logic that overwrites the Jekyll category variables.

Django dropdown divider

I have a dropdown menu that i generated by looping through a list of objects. I have a divider after object 0, 10, and 13. However some user don't have access to all objects so the dividers dont show. Can someone suggest a good way have after the last object in each bucket. I.e. bucket [0], [1-10], [11-13]. They buckets are areas in different states.
I'm not necessarily asking for someone to write the code for me. I'm just asking how to do this conceptually as I'm quite new to coding and Django. Any help is much appreciated!
<ul class="dropdown-menu">
{% for i in area_list %}
{% if not i.area_id == area.area_id %}
{% if i.area_id == 0 or i.area_id == 10 or i.area_id == 13 %}
<li>{{ i.area_name }}</li>
<li class="divider"></li>
{% else %}
<li>{{ i.area_name }}</li>
{% endif %}
{% endif %}
{% endfor %}
</ul>
See forloop.last. Try:
context['zones'] = (area_list[:1], area_list[1:11], area_list[11:])
and:
<ul class="dropdown-menu">
{% for areas in zones %}
{% for i in areas %}
{% if not i.area_id == area.area_id %}
<li>{{ i.area_name }}</li>
{% endif %}
{% endfor %}
{% if not forloop.last %}
<li class="divider"></li>
{% endif %}
{% endfor %}
</ul>
You can also prepare the zones and filter empty zones in your view.

Sorting/grouping collections for an archive

I am building my first site and am having a very difficult time grouping/sorting collections. The only success I have had is a list of files sorted alphabetically by subdirectory, then by files by their dates (seems to be the default) using:
<ul>
{% for page in site.collection_name | sort: weight %}
<h3>{{ page.title }}</h3>{{ page.category }}{{page.excerpt}}
{% endfor %}
</ul>
Weight (above) does not work. Neither did type, category, or any other variable I substituted.
My files are in subdirectories, and have permalinks as:
/collection_name/category_name/file_name/
Front matter includes:
title,
category,
layout,
type,
(tried several others)
The collection will have several file types such as:
articles,
videos,
research
What I want to accomplish is something that loops through my collection first for category, then by type. In very bad pseudo code:
<ul>
{% for page in site.{{category_name}} %}
<li><h2>{{category01}}</h2></li>
<ul>
{% for type in site.{{category_name.type}} | sort: date reverse%}
<li><h3>Articles</h3></li>
<li>{{ page.title }}{{page.excerpt}}</li>
<li><h3>Videos</h3></li>
<li>{{ page.title }}{{page.excerpt}}</li>
<li><h3>Research</h3></li>
<li>{{ page.title }}{{page.excerpt}}</li>
</uL>
<li><h2>{{category02}}</h2></li>
. . .
. . . {% endfor %}
Any help or direction will be appreciated.
Try to use group_by :
{% assign byCategory = site.collection_name | group_by: 'category' | sort: 'name' %}
{% for cat in byCategory %}
<h2>{{ cat.name | capitalize }}</h2>
{% assign byType = cat.items | group_by: 'type' %}
{% for type in byType %}
<h3>{{ type.name | capitalize }}</h3>
<ul>
{% for item in type.items %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
Note: this works with category: mycategory not with categories: [one, two]
If you want to specifically order types, you can do :
_config.yml
# this array determine types order
# a collection itm with non matching type will not be listed
types :
- articles
- videos
- research
code
{% assign byCategory = site.area | group_by: 'category' %}
{% for cat in byCategory %}
<h2>{{ cat.name }}</h2>
{% assign byType = cat.items | group_by: 'type' %}
{% for type in site.types %}
{% assign currentType = byType | where:"name", type | first %}
<h3>{{ currentType.name | capitalize }}</h3>
<ul>
{% for item in currentType.items %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}

Jekyll, Liquid - Get all pages from category from page

I have a question in Jekyll Liquid.
I have layout, where I want to show pages from category. To show category I use page.categories variable. When I show in bracket {{page.categories}} is correct.
but I don't know, how to pass to loop?
{% for post in site.categories[page.categories] %}
<li>{{ post.title }}</li>
{% endfor %}
{% for post in site.categories[{{page.categories}}] %}
<li>{{ post.title }}</li>
{% endfor %}
Don't work.
If I passed explicite:
{% for post in site.categories['cat1'] %}
<li>{{ post.title }}</li>
{% endfor %}
It works.
I found another topic:
Jekyll site.categories.{{variable}}?
But it doesn't work.
page.categories is a list (see Page Variables), so you need to loop through it first and pass each category to the loop from your question:
{% for cat in page.categories %}
<h1>{{ cat }}</h1>
<ul>
{% for post in site.categories[cat] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
This will first display all posts for the page's first category in descending order, then all posts for the page's second category in descending order, and so on.
Thank you. It's work.
Also I can use this code (use first on element of array, because in my case I have only one category per page):
{% assign pcat = page.categories %}
<ul>
{% for post in site.categories[pcat.first] %}
<li {% if post.url == page.url %}class="active"{% endif %}>{{ post.title }}</li>
{% endfor %}
</ul>

How to iterate WTForms FieldList with Jinja2

As the title says, here's what I've got:
form = F(obj = myobject)
myfieldlist= FieldList(FormField(form))
{% for subfield in form.myfieldlist %}
{{ subfield.field }}
{{ subfield.label }}
{% endfor %}
This outputs nothing, any ideas? Also, not entirely sure if FormField is required.
Thanks
FormField takes a class not an instance:
class GuestForm(Form):
email = TextField()
vip = BooleanField()
class VenueForm(Form):
name = TextField()
guests = FieldList(FormField(GuestForm))
Then in your controller:
form = VenueForm(obj=myobject)
render("template-name.html", form=form)
In your template you will need to iterate over the FieldList field as if it was its own form:
{% for guest_form in form.guests %}
<ul>
{% for subfield in guest_form %}
<li>{{ subfield.label }} {{ subfield }}</li>
{% endfor %}
</ul>
{% endfor %}