I want to do something like this:
Entries.objects.values('date.year','date.month')
but this line is not valid. How can I list blog entries by year,month and display them in template?
Thanks!
If you set
entry_list = Entry.objects.order_by('pub_date')
in your view, you can display the months and years in the template using the ifchanged template tag.
{% for entry in entry_list %}
{% ifchanged %}<h3>{{entry.pub_date|date:"Y"}}</h3>{% endifchanged %}
{% ifchanged %}<h4>{{entry.pub_date|date:"F"}}</h4>{% endifchanged %}
<p>{{entry.title}}</p>
{% endfor %}
Another useful Django queryset method for blog archives is dates.
For example
entry_months = Entry.objects.dates('pub_date','month','DESC')
returns a DateQuerySet of datetime.datetime objects for each month that has Blog Entries. You can use this queryset in the template to create links to monthly archive pages.
You can try with the built-in regroup tag.
In your view:
archives = Entries.objects.all()
In your template:
{% regroup archives by date.month as entries_by_month %}
{% for entries in entries_by_month %}
<h1>{{ entries.list.0.date|date:"F Y" }}</h1>
<ul>
{% for entry in entries.list %}
<li>{{ entry.title }}</li>
{% endfor %}
</ul>
{% endfor %}
Here is some code snipped from my blog where I list all of the blog entries within a certain year:
Entries.objects.filter(draft=drafts).filter(posted_date__year=year).order_by(order_by)
In the above:
drafts is a boolean which specifies whether to show completed items or not.
year is the selected year
order_by is some ordering column name.
You should be able to easily modify this example to also include the month.
The above shows that you can combine multiple filters in a row.
Ok, let's try to do heavy lifting in data structure, instead of templates.
Let's create a utility.
import itertools
def group_by_values(posts, key):
groups = {}
for k, g in itertools.groupby(posts, key):
if groups.get(k) is not None:
groups[k].extend(list(g))
else:
groups[k] = list(g)
return groups
Let's use the utility here.
entries = Entry.objects.all().order_by('date')
yearly_entries = group_by_values(entries, key=lambda x: x.date.year)
monthly_yearly_entries = {}
for k, v in yearly_entries.items():
monthly_yearly_entries[k] = group_by_values(v, key=lambda x: x.date.month)
return monthly_yearly_entries
The result is nice dictionary with years and months as keys like this:
monthly_yearly_entries = {2013: {9: [Entry1, Entry2], 10: [Entry4, Entry5]}}
which you can show nicely in templates
Related
What am I trying to achieve will be easier to explain on lists.
e.g
list_of_blocks=[1,2,3,4,5,6,7,8,9,10,11,12]
block_first_row = list_of_blocks[:3]
block_rest_rows = [list_of_blocks[i:i+4] for i in range(3, len(list_of_blocks), 4)]
block_rows = block_rest_rows.insert(0, list_of_blocks)
I want to group blocks from StreamField and display them in template grouped by those rows.
Is there a way to do it in my model? Or should i do it somehow in template..
I've tried to do:
operate on StreamField as on list
deconstuct StreamField.. then operate as on list
The value of a StreamField is a list-like object of type StreamValue. Since it isn't a real list, it may not support slicing - if not, you can get around that by casting it to a real list with list(self.body) (where body is your StreamField). A good place to do this is the page's get_context method:
def get_context(self, request):
context = super().get_context(request)
list_of_blocks = list(self.body)
block_first_row = list_of_blocks[:3]
block_rest_rows = [list_of_blocks[i:i+4] for i in range(3, len(list_of_blocks), 4)]
block_rows = block_rest_rows.insert(0, block_first_row)
context['block_rows'] = block_rows
return context
You can then access block_rows in your template:
{% for block_row in block_rows %}
<div class="row">
{% for block in block_row %}
render block as normal, with {% include_block block %} or otherwise
{% endfor %}
</div>
{% endfor %}
i made i dictionary of querysets in one of my views :
list =[]
while(x<100 and i>0):
order_qs_1 = Order.objects.filter(timestamp__range=[start_date, end_date])
x = x+1
i=i-j
list.append(order_qs_1)
context= {
'list':list,
}
but now i don't know how to access the data inside the dictionary in my template
in my template i did something like this :
{% for item in list %}
{{ item }} </br>
{% endfor %}
this is what it renders:
the random numbers and characters are the order_id in my order model
the queryet is a list of orders coming from my order model
but this not what i want , i want the access the data inside each queryset
You can iterate over the querysets. For example:
{% for qs in list %}
<p>
{% for order in qs %}
{{ order }}
{% endfor %}
</p>
{% endfor %}
Here we thus iterate over the querysets qs, and for example render the order. You can thus render individual data of that order, for example {{ order.pk }} for the primary key.
I have line of code in Django template:
<h4>{{ totals.date.weekday }}</h4>
Totals is the Python list, how do i get item of this list by index stored in date.weekday?
This would look in Python like this:
totals[date.weekday]
Creating another variable, which stores date.weekday doesn't work
UPD:
I found a solution:
Just added element of totals list to template context in render
For example:
# ...
return render(request, 'template.html', context={'date_total'=totals[date.weekday()]})
You can access the array directly using
{{ totals.0.date.weekday}} where the 0 is the position that you want.
Also if you want to print all the elements in total you will need a for loop such as:
{% for d in totals %}
{{ d }}
{% endfor %}
about sorting, you can use the pipe order_by but I recommend you to pass the list already ordered from the views
You have to run the "for loop" for this.
{% with counts = 0 %}
{% while counts < totals.count %}
{% if counts == date.weekday %}
<h4>total.counts</h4>
{% endif %}
{% counts += 1 %}
{% endfor %}
I did not get your question completely but i think it might help.
def playerData(request, player_id):
r = requests.get("https://api.opendota.com/api/players/" + str(player_id) +"/matches/?limit=20")
last20matches = json.loads(r.text)
return render (request, "playerstats.jinja", {'last20' : last20matches,'playerid' : player_id})
{% for entry in last20 %}
<li>
{% entry["match_id"] %}
</li>
{% endfor %}
so in my playerData function I get a players last 20 matches and set it to r.
last20matches is a list of 20 dictionaries.
Now to the template.
I'm going through every dictionary ( each dictionary is a match ) and I want to create a link to a page (https://www.dotabuff.com/matches/match_id).
However, the match_id is in the dictionary with key match_id. How do I get this into my link in the html file?
Error:
Invalid block tag on line 20: 'entry["match_id"]', expected 'empty' or 'endfor'. Did you forget to register or load this tag?
You have two mistakes. Firstly, variables are always denoted by {{ ... }}, not {% ... %} which is for tags. Secondly, all lookups - including dictionaries - in a Django template are done via dot notation, not square brackets.
So:
{{ entry.match_id }}
Hi I have the following query in my views.py
m = Request.objects.filter(Q(type__icontains='4'), Q(wt__in =['giga','mega']))
context['all_items'] = m.values('type1').order_by('type1')
Its giving values sasoo, masoo, pisoo, kusoo etc.
How can I implement the Django Substr in this case so that my html will display values as sa, ma, pi, ku, ..
You can annotate the model
from django.db.models.functions import Substr
m = Request.objects.filter(Q(type__icontains='4'), Q(wt__in =['giga','mega']))
context['all_items'] = m.annotate(mysubstring=Substr('type1',1,2)).order_by('type1')
In template:
{% for obj in all_items %}
{# Use obj.mysubstring #}
{% endfor %}
You can use slice filter in your template:
{% for item in all_items %}
{{ item.type1|slice:":2" }}
{% endfor %}
One liner
context['all_items'] = [i[:2] for i in context['all_items']]