django DateTimeField list records by day - django

Hay, i have a field in one of my models which saves the creation date of an object
created_on = models.DateTimeField(blank=False, auto_now_add=True)
This works as expected.
In my templates i want to list objects like this
June 15
{{ objects here which was created on June 15 }}
June 14
{{ objects here which was created on June 14 }}
etc
Any idea how i would go about doing this?
Thanks in advance.

First in the view, make sure your objects are ordered by the 'created_on' field.
object_list = MyObjs.objects.all().order_by('created_on')
I believe you should then be able to use the following code in your template:
{% regroup object_list by created_on|date:"Y-m-d" as objects_by_day %}
{% for day in objects_by_day %}
{{day.list.0.created_on|date:"M d"}}
{% for obj in day.list %}
{{obj}}
{% endfor %}
{% endfor %}
This makes use of the regroup template tag, grouping the items by day, creating a list of objects per day. The date itself is output by using the 'date' template filter to reformat the created_on field of the first item in that date's list.
[Note: I have not tested this!]

The place for this is in the template, not the view.
You want the ifchanged template filter, which you use like this:
<h1>Archive for {{ year }}</h1>
{% for entry in entries %}
{% ifchanged %}<h3>{{ entry.date|date:"F" }}</h3>{% endifchanged %}
<p>{{ entry.date|date:"j" }} - {{ entry.title }}</p>
{% endfor %}
In this example, every time the month changes, a heading showing the month will be printed.
ifchanged can do some relatively complex things (e.g. checking if multiple variables have all changed), and can have an optional else block - see the docs for more.

you can for example generate list of dates(by day on given interval) in your view ordered from min to max, and get all objects in this interval. Then create templatetag that takes 2 arguments queryset and date,
and filter records which created(or something else) by your date.

Related

Django querysets. How to prefetch only unique?

Models:
class House(Model)
class Flat(Model):
house = ForeignKey(House, related_name="houses")
owner = ForeignKey(User)
class User(Model)
queryset:
queryset = User.objects.prefetch_related(
Prefetch("flats", queryset=Flat.objects.select_related("houses"))
And then flats:
{% for flat in user.flats.all %}
<p>№ {{ flat.number }}, {{ flat.house.name }}</p>
{% endfor %}
It's fine. But for houses I need only unique ones
{% for flat in user.flats.all %}
<p>House {{ flat.house.name }}</p>
{% endfor %}
But this template gives me ALL houses, with duplicates.
How can I avoid duplicates, any ideas? I tried .distinct() but it's dosen't work, looks like I using distinct() wrong or etc.
It seems you may end up with duplicate houses if a user is the owner of multiple flats, which are all in the same house. To get all houses that the user is related to via Flats, you can use a different query, starting with House so that you can use distinct:
distinct_houses = House.objects.filter(flats__owner=user).distinct()
The above returns one House object for each flat where the user is an owner, and makes sure you don't have duplicates. (Note that the above assumes the related_name is changed to flats for house = ForeignKey(House, related_name="flats"), since "houses" as the related_name seems like a typo to relate back to the Flat model.)
Alternatively, you could do something in-memory in Python, if you still also need to know all Flats via your original queryset = User.objects.prefetch_related(...) and don't want an additional query. Like:
distinct_houses = {flat.house for flat in user.flats.all()}
Side note: it looks like you have a typo in needing to use Flat.objects.select_related('house') rather than Flat.objects.select_related('houses') based on the Foreign Key field name being house.
Only found solution with template filters.
Queryset:
queryset = User.objects.filter(status="ACTIVE").prefetch_related(
Prefetch("flats", queryset=Flat.objects.select_related("house"))
)
With this I can get all flats for each user:
{% for user in object_list %}
{% for flat in user.flats.all %}
{{ flat.number }}, {{ flat.house.name }}
{% endfor %}
{% endfor %}
And I am using template filter to get unique houses.
{% for user in object_list %}
{% for flat in user.flats.all|get_unique_houses %}
{{ flat.house.name }}
{% endfor %}
{% endfor %}
# extra_tags.py
#register.filter(name="get_unique_houses")
def get_unique_houses(value):
return value.distinct('house')

Remove duplicate values in django forloop

i have some dates in a list and I want to display all days in the list using forloop at Django template. what I want is to remove duplicate days in it.
here is the sample code
{% for part_time_day in part_time %}
{{part_time_day.start_time|date:"D"}},
{% endfor%}
it will display all the days like "Sun, Mon, Fri, Sun" etc but I want to remove duplicate days so one day can display only once
Django template has a ifchanged tag:
{% for part_time_day in part_time %}
{% ifchanged %} {{part_time_day.start_time|date:"D"}}{% endifchanged %},
{% endfor%}
It looks if the content has changed from previous iteration. So it will work better if you have ordered by start_time before.

How to filter objects from template?

I have 2 models Category and Spending where Category is one of the Spending fields.
User can create custom categories and add spending on the webpage.
The question is, how to filter spendings by categories in Template?
I have:
{% for category in categories %}
{% for spending in spendings %} 'I want this FOR have only spendings from this category.'
I know how to filter objects with Object.objects.filter() but I am not sure it applies here, because categories are dynamic here
Use the reverse relation. You haven't shown your models, but presumably there is a foreign key from Spending to Category. If so:
{% for spending in category.spending_set.all %}
You can do this way.
{% for category in categories %}
{% for spending in category.spending_set.all %}
{{spending}}
{% endfor %}
{% endfor %}

Django how to list model objects date wise

I have a model from which I need to list all the objects from a given time period.
For example: 10-05-2014 to 10-12-2014
And then I need to display the objects date wise. Meaning first display objects created on the start_date(10-05-2014) up until end_date(10-12-2014)
For example:
10-05-2014:
objects list for that day
11-05-2014:
objects list for that day
and so on until end_date
Query:
MyModel.objects.unsettled.filter(
created_on__range=[start_date, end_date]
)
But my problem is how do I list the query set in increasing order by date wise in my template. So that all the objects created on same date will be shown under that date. In short I want to display the list in sections divided by date.
MyModel.objects.unsettled.filter(created_on__range=[start_date, end_date]).order_by("created_on"). But it will just sort the list. How do I group the results.??
Use the {% ifchanged %} template tag:
{% for obj in obj_list %}
{% ifchanged %}
<h2>{{ obj.created_on|date }}</h2>
{% endifchanged %}
<div>{{ obj.name }}</div>
{% endfor %}
Another (slightly more complex) option is to use the {% regroup %} tag.

Can I reduce queries while iterating a RelatedManager object within a template?

This is a hypothetical for simplicity. In my Django app I have models for Kit, KitSku, and Sku. The KitSku model associates a Sku with a Kit and also provides the quantity of that Sku in that kit. In the template I have something like:
<!-- SELECT * FROM kitsku_table WHERE kit_id = <Kit.id> -->
{% for kitsku in kit.kitsku_set.all %}
<!-- SELECT * FROM sku_table WHERE sku = <KitSku.sku> -->
<div>{{ kitsku.sku.name }}</div>
{% endfor %}
Now, the problem here is that Django is querying all of the KitSku rows and then it queries each sku within that for loop in a separate SQL query for each iteration.
Can I make the SQL query resulting from the kitsku_set.all() call perform a JOIN with the Sku model?
That first query needs to be more like:
SELECT * FROM kitsku_table k LEFT JOIN sku_table s ON (k.sku = s.sku)
WHERE k.kit_id = <Kit.id>
Do this type of logic in the view, and use select_related() to directly query the foreign keys
kitskus = Kit.objects.get(id=3).kitsku_set.select_related('sku')
return direct_to_template(request, "mytemplate.html", {'kitskus': kitskus})
Im just copying an answer for a similar question, but i think this is a much better approach.
view
newsletters = Newsletter.objects.prefetch_related('article_set').all()\
.order_by('-year', '-number')
return render_to_response('newsletter/newsletter_list.html',
{'newsletter_list': newsletters})
template
{% block content %}
{% for newsletter in newsletter_list %}
<h2>{{ newsletter.label }}</h2>
<p>Volume {{ newsletter.volume }}, Number {{ newsletter.number }}</p>
<p>{{ newsletter.article }}</p>
<ul>
{% for a in newsletter.article_set.all %}
<li>{{ a.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}
Here is the complete explanation:
Hopes it helps
Iterating over related objects in Django: loop over query set or use one-liner select_related (or prefetch_related)