I am trying to display sets of three objects in a HTML template in a tiled interface. So, for example, an Album model has a ManyToMany field with specific photos. I want to iterate through the photos and show them in sets of three in the view. Currently, I can get all the photos using {{ for photo in album.images.all }} in the template, but don't know how to get the results in sets of three.
How would I go about chunking the results into sets of three so that I can then iterate through the sets of three for the template? Or is there a way to get the total length and then index of specific elements using the Template tags?
Thanks
{% for photo in album.images.all %}
{{ photo }}
{% if forloop.counter|divisibleby:4 %}
<hr> {# or some other markup #}
{% endif
{% endfor %}
You might also do the grouping in your view. This might result in cleaner markup. See: Django template {%for%} tag add li every 4th element
Related
I have Django model with CharFields 'flname1', 'date1', and 'time1'. My goal in my HTML is to have a {{ forloop }} that runs through only the 'date1' and 'time1' fields and displayed all of them. My Problem is that in my views file I can't find a way to create a python variable that only contains two of the three fields from one model. Ie tried a lot but what I'm trying to avoid is...
posts = DocPost.objects.all()
This puts all three fields into a variable and displays them in my for loop which I don't want. I've also tried a lot of work with filters and go things that other people on the internet had success with that didn't work for me like...
posts = DocPost.objects.filter('flname1').only('date1', 'time1')
This didn't work and didn't section off date1 and time1 and pack them away in a variable that I could loop through. Ive tried a lot more than this at this point to no prevail. Thank for any help.
There are two things you can do to only get certain fields in a query and iterate over them. The template for both is pretty much the same
First, you can use only() to generate a queryset where each object only has certain fields populated and all the rest are deferred
# View
context['posts'] = DocPost.objects.only('date1', 'time1')
# Template
{% for post in posts %}
{{ post.date1 }}
{{ post.time1 }}
{% endfor %}
Second, you can use values() to generate a queryset of dictionaries that only contain the fields specified
# View
context['posts'] = DocPost.objects.values('date1', 'time1')
# Template
{% for post in posts %}
{{ post.date1 }}
{{ post.time1 }}
{% endfor %}
I would like the visitors to my site to land on a category page, not on the default index.html. I want them to see the articles in the News categories before anything else.
Maybe is there a way to tell Pelican to output category/news to index.html? I know this would be possible with normal handwritten pages using the save_as field, but how can I do it with an automatic page generated by Pelican?
Your homepage, the index.html file, is just another template from the DIRECT_TEMPLATES list. It'll depend on your theme exactly how it is generated, but you can always override specific templates locally, or you can create a new template for your homepage to replace it (and optionally redirect the original index.html generated page to a different location).
Either way, you can then generate a section that shows the articles from a single category. All template pages are given the same basic variables, which includes the articles list, as well as a categories list with (Category, list_of_articles) tuples.
The easiest way to get all articles for a single, specific category is to filter the articles list directly with the Jinja2 selectattr filter. selectattr('category', '==', categoryname) is matched both against the category name or the slug (whatever you set categoryname to is converted to a slug for you). So if your category is named News, then both 'News' or 'news' works:
<h2>News:</h2>
<ol id="posts-list" class="hfeed">
{% for article in articles | selectattr('category', '==', 'news') %}
<li><article class="hentry">
<header>
<h1><a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark"
title="Permalink to {{ article.title|striptags }}">{{ article.title }}</a></h1>
</header>
<div class="entry-content">
{% include 'article_infos.html' %}
{{ article.summary }}
<a class="readmore" href="{{ SITEURL }}/{{ article.url }}">read more</a>
{% include 'comments.html' %}
</div><!-- /.entry-content -->
</article></li>
{% endfor %}
</ol>
The above reuses the simple theme article markup. You may want to limit the number of news articles; in that case use the batch(size) filter together with first:
<h2>News:</h2>
<ol id="posts-list" class="hfeed">
{% for article in articles | selectattr('category', '==', 'news') | batch(5) | first %}
<!-- render article, etc. -->
The above takes the first 5 articles with News as the category.
Since the basic theme reuses the index.html template for all of the individual archive pages too (for each category, author or tag page), I'd not override the index direct template here. Instead, I'd create a new homepage template (in the pages directory) and write that to index.html and. You need to add the template in the TEMPLATE_PAGES dictionary, where your template pages should live in a separate directory that is configured not to be treated as articles or pages.
Create a new directory for template pages in your content directory; you'll need to make sure Pelican doesn't try to treat files there as articles, so add it to the ARTICLE_EXCLUDES list. So if all your Pelican your content lives in content/, and you have a file homepage.html in the directory output/templates/, you'd use:
ARTICLE_EXCLUDES = ['templates']
TEMPLATE_PAGES = {
'templates/homepage.html': 'index.html',
}
This will overwrite the default index.html generated for articles, there is no need to remove anything from DIRECT_TEMPLATES but you could do so to avoid generating a file you never keep.
The homepage.html template can make full use of any existing templates in the theme, so you can just extend base.html that most themes will have defined:
{% extends "base.html" %}
{% block content %}
<section id="content">
<h2>Recent news:</h2>
<ol>
{% for article in articles | selectattr('category', 'equalto', 'news') | batch(5) | first %}
<!-- markup for each news item -->
{% endfor %}
</ol>
</section><!-- /#content -->
{% endblock content %}
Instead of overwriting the default index, you can also set INDEX_SAVE_AS to direct the original index.html file elsewhere:
ARTICLE_EXCLUDES = ['templates']
TEMPLATE_PAGES = {
'pages/homepage.html': 'index.html',
}
# move the original article index elsewhere:
INDEX_SAVE_AS = 'all_articles.html'
If you use a theme that doesn't reuse the index.html template for more pages or you want to try to make the template work for in those contexts anyway, then you can override the template used for index instead. To override the default index.html from your theme, create a local directory (overrides perhaps) to put your local version into, then add that directory to the THEME_TEMPLATES_OVERRIDES list in your configuration:
THEME_TEMPLATES_OVERRIDES = ['overrides']
Now when Pelican tries to load the index.html template to render the index direct template, it'll look for overrides/index.html first. So in overrides/ add your own index.html:
{% extends "base.html" %}
{% block content %}
<section id="content">
<!-- put your desired content here -->
</section><!-- /#content -->
{% endblock content %}
A word on pagination: all templates, except for the special per-archive-type pages (categories, authors, tags, periods), are paginated on the full articles list, this isn't something that is further configurable. This means you can't paginate a homepage on a single category of articles.
This means that if you override the index.html template and removed the full article listing, then you may want to remove index from the PAGINATED_TEMPLATES dictionary so it isn't re-generated multiple times to match your article list.
I have a very basic template (basic_template.html), and want to fill in the with data formatted using another partial template. The basic_template.html might contain several things formatted using the partial template.
How should I structure the code in views.py?
The reason I am doing this is that later on the will be filled using Ajax. Am I doing this right?
You can do:
<div class="basic">
{% include "main/includes/subtemplate.html" %}
</div>
where subtemplate.html is another Django template. In this subtemplate.html you can put the HTML that would be obtained with Ajax.
You can also include the template multiple times:
<div class="basic">
{% for item in items %}
{% include "main/includes/subtemplate.html" %}
{% endfor %}
</div>
You can do this using a block. Blocks are a Django Template tag which will override sections of a template you extend. I've included an example below.
basic_template.html
<body>
{% block 'body' %}
{% endblock %}
</body>
template you want to include: (i.e. example.html)
{% extends 'basic_template.html' %}
{% block 'body' %}
/* HTML goes here */
{% endblock %}
views.py:
return render_to_response(template='example.html', context, context_instance)
Doing this will load basic_template.html, but replace everything inside of {% block 'body' %} {% endblock %} in basic_template.html with whatever is contained within {% block 'body' %} {% endblock %}.
You can read more about blocks and template inheritance in the Django Docs
There are mainly 2 ways (2 easy ones)
1:
In base html put
{% include "myapp/sub.html" %}
And just write html code inside your sub.html file
2:
https://docs.djangoproject.com/en/dev/ref/templates/language/#template-inheritance
I just wanted to add differences of extend and include.
Both template and include can use models inserted in current app.
Template is for global usage by your any app. Include is for use in certain apps.
For ex: you want to insert Image Slider to your homepage and about page but nowhere else. You can create Slider app with its own model for convenience and import its model and include in that pages.
If you used template for this example, you would create 2 templates one with slider and everything else other template have.
I have managed to create the forms I need using modelformset_factory.
avaluos = Avaluo.objects.filter(Estatus__contains='CONCLUIDO',Factura__isnull=True)
FacturaFormset = modelformset_factory(Avaluo,form=FacturaForm,extra=0)
Currently this is generating the following HTML for each of the rows found:
<form id="id-FacturaForm" class="blueForms" method="post">[..]</form>
<form id="id-FacturaForm" class="blueForms" method="post">[..]</form>
<form id="id-FacturaForm" class="blueForms" method="post">[..]</form>
I want to submit all the forms using a single submit button.
Any ideas?
UPDATE
I ended up using django-crispy-forms which allowed me to gerate inputs for each row, and then I just manually added the form and submit.
self.helper.form_tag = False
{{example_formset.management_form }}
{% for a,b in olist %}
{{ b.id }}
<tr>
<td style="width:10px;"> {% crispy b %} </td>
<td> {{a.id}} </td>
</tr>
{% endfor %}
Read more into model formsets. You don't need to have separate form tags, it's the whole point of using a formset.
<form method="post" action="">
{{ factura_formset.management_form }}
<table>
{% for form in factura_formset %}
{{ form }}
{% endfor %}
</table>
</form>
Also, every time you use the id attribute more than once on a pageā¦ a developer cries themselves to sleep somewhere in the world.
I suspect you will need to do it using Ajax - otherwise as soon as one form is submitted you will not be able to go the other way.
There are a few jQuery form libraries that should make it relatively straightforward. For example, http://malsup.com/jquery/form/.
It would look something like:
$('#button-id').click(function() {
$('.blueForms').ajaxSubmit();
});
Of course, you'll then need to deal with error handling and waiting for all the forms to have submitted.
If you're trying to create many instances of the "same" form (this is, they all look equal), as if it were one of many childs belonging to a single, master element, you don't actually need to create a form tag for each of the formsets.
If I'm not mistaken, you're trying to edit many facturas for a single avaluo object. Am I right? The representation would be a single "avaluo" form with many inline formsets, one for each "factura".
Check out the inline formsets factory instead of the modelformset factory.
When using Django templates, should I have some templates that act like "subroutines", so to speak, or should I generate HTML from within my code in these cases?
For example, I have a template with several lists of names, each of which I want to turn into a select. Should I have a template that renders the name_list variable into a select, and do something like this:
#in the view:
return {'name_list_1': name_list_1,
'name_list_2': name_list_2,
'name_list_3': name_list_3}
#in the template:
{% with name_list_1 as name_list %}
{% include "sub_name_list_select.html" %}
{% endwith %}
{% with name_list_2 as name_list %}
{% include "sub_name_list_select.html" %}
{% endwith %}
{% with name_list_3 as name_list %}
{% include "sub_name_list_select.html" %}
{% endwith %}
Or should I have a function in my code, name_list_to_select_html, which does the same job, and do this:
return {'name_list_1_html': name_list_to_select_html(name_list_1),
'name_list_2_html': name_list_to_select_html(name_list_2),
'name_list_3_html': name_list_to_select_html(name_list_3)}
#in the template:
{{ name_list_1_html|safe }}
{{ name_list_2_html|safe }}
{{ name_list_3_html|safe }}
Or are both of these wrong and I am getting the philosophy totally wrong?
Additional question: in terms of speed, is it slow to constantly include templates? Is that a bonus point for the in-code html generation?
Generally, HTML should only be generated in the templating system or directly related code. That keeps the view of the data completely separate from the business and functional logic. I feel that's a proper separation of concerns. Go with your first solution.
As for performance, Django should probably take around the same amount of time running either code. But it has built-in view and template fragment caching if you know those segments of code don't need to be regenerated on every request.