Django Stopping loop after x times within a template - django

I have queryset that returns many records but in the template I use it twice to return value.
For example:
On one instance I need to return the latest 5 posts and then show all the posts on that same page. So for that reason I can't use LIMIT in my queryset.
{% for post in blog_posts %}
<li>{{ post.title }}</li>
{% endfor %}
From that example how can I stop to loop after 5 times.

Use the slice filter:
{% for post in blog_posts|slice:":5" %}
<li>{{ post.title }}</li>
{% endfor %}

Related

tags are not getting displayed in template, Django

context['d_tags'] = Blog.objects.filter(is_published=True).values('tags__name').order_by('tags__name').distinct()
print(context['d_tags'])
this prints the out put as below
<QuerySet [{'tags__name': 'ev'}, {'tags__name': 'yoga'}]>
how can I show it on templates, tried the following way
{% for tag in d_tags.all %}
<li>{{ tag }}</li>
{% endfor %}
gives an out put in template as
{'tags__name': 'ev'}
{'tags__name': 'yoga'}
but if I do this way
{% for tag in d_tags.all %}
<li>{{ tag.name }}</li>
{% endfor %}
doesn't gives any thing in display, how I can get just the values in template
You said #root's solution doesnt work, but it should... Are you sure you tried {{tag.tags__name}} and not something else?
Another solution would be opening double for loops...
{% for tag in d_tags %}
{% for tag_name in tag %}
<li>{{ tag_name }}</li>
{% endfor %}
{% endfor %}
But hey, thats really the same thing as saying {{tag.tags__name}}

Django: How to get the first word of a string in an HTML template?

Problem
I am passing a list to my HTML template and the list looks like this:
Chemical Engineering
Civil Engineering
Computer Engineering
Electrical Engineering
Electronics Engineering
...
My Goal
I want to grab the first word (I would like to remove the "engineering" in all of them). I'm displaying the list in my HTML template like this:
{% for course in courses %}
<li>{{ course }}</li>
{% endfor %}
What I tried
I tried the following syntax:
{% for course in courses %}
<li>{{ course.split[0] }}</li>
{% endfor %}
{% for course in courses %}
<li>{{ course[0] }}</li>
{% endfor %}
{% for course in courses %}
<li>{{ course|first }}</li>
{% endfor %}
The third one above only gives me the first letter of each string. I know that I can do truncate but not all of them have the same number of characters. I also tried to do
this but to no avail. Maybe my syntax was wrong? What other solutions can I try? Thanks in advance!
Based on schwobaseggl's comment, he mentioned trying the syntax course.split.0 and it worked for me.
Try this one,
{% for course in courses %}
{% set words = course.split(' ') %}
<li>{{ words[0] }}</li>
{% endfor %}

django template print only first unique occurance

I have a pretty simple task to do but I do not know how to do it most effectively in django templates.
Basically, this is what I am trying to accomplish:
Jan. 27, 2015
first post
second post
third post
Jan. 28, 2015
another post
and other
etc
Feb. 18, 2015
again
and again
This could be its model:
class Post(models.Model):
date=models.DateField()
name=models.CharField()
In views.py passing just queryset as posts:
Post.objects.filter(date__gte = date.today()).order_by("date")
And then in template priting it out with for cycle:
{% for post in posts%}
{{post.name}}
{% endfor %}
How do I get printed unique date only once? Is it possible to do this in templates or do I have to take care of it in views? I found similar two year old post.
There is an inbuilt template tag for that - regroup!
This isn't perfect, but with the documentation it should get you close.
{% regroup posts by date as date_list %}
<ul>
{% for date in date_list %}
<li>{{ date.grouper }}
<ul>
{% for item in date.list %}
<li>{{ date.name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
You can use {% ifchanged %} template tag:
{% for post in posts %}
{% ifchanged %}<h3>{{ post.date }}</h3>{% endifchanged %}
<div>{{ post.name }}</div>
{% endfor %}

How to get related set models without hit database in Django

Here you'll always get two separate db calls, and adding select_related() anywhere won't help at all. One extra db call isn't that significant.
<ul>
{% for obj in myobjects %}
<li>{{ myobj.name }}</li>
<ul>
{% for relobj in myobj.backwardsrelationship_set.all %} {# hit database at every row #}
<li>{{ relobj.name }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
Any idea here?
I found the solution.
prefetch_related can solve this
Publisher.objects.filter(city='NY').prefetch_related('book_set')

Using custom object manager on related set

Im trying to print out 4 entries. It works, as long I don't have any entries not published.
How can I get a queryset that only contains objects from my "published" manager?
Now I use: {% if benefit.status == "p" %} to not print those entries not published, but then the unpublished effects the slice count.
#views.py:
class PackageListFrontpage(ListView):
context_object_name = "package_frontpage_list"
template_name = "frontpage.html"
queryset = Package.published.all().order_by('order')[:5]
#frontpage.html
{% for package in package_frontpage_list %}
<div>
<h3>{{ package.name }} >></h3>
<ul>
{% for benefit in package.benefit_set.all|slice:":4" %}
{% if benefit.status == "p" %}
<li>{{ benefit.name }}</li>
{% endif %}
{% empty %}
<li>There are no published benefits in this package</li>
{% endfor %}
</ul>
</div>
{% endfor %}
I guess there is a better way of doing this?
You could define a method on your Package model that returns the queryset of related benefits which are published.
class Package(object):
...
def benefit_set_published(self):
"""
Return the related benefits which are published
"""
return self.benefit_set.filter(status="p")
Then change your template to:
{% for benefit in package.benefit_set_published.all|slice:":4" %}
<li>{{ benefit.name }}</li>
{% empty %}
<li>There are no published benefits in this package</li>
{% endfor %}