I'm not sure how to ask this question but I'll give it a shot.
I am writing a Todo application and want to display each todo under its respective category in the template. For example
Display each category
{% for category in categories %}
<h2>{{ category.name }}</h2>
Now show each todo that falls under the above category
{% for todo in todos %}
<p>{{ todo.description }}</p>
{% endfor %}
{% endfor %}
How do I create a queryset that will give my this type of structure? Or is there are different way to achieve this?
If something is unclear or require more info let me know and I'll add it to the post
Any help is appreciated, thank you.
Models
class Category(models.Model):
name = models.CharField(max_length=20)
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.name
class Todo(models.Model):
# Priority choices
PRIORITY_CHOICES = (
("bg-danger", "High"),
("bg-info", "Normal"),
("bg-warning", "Low"),
)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
description = models.CharField(max_length=255)
priority = models.CharField(max_length=200, choices=PRIORITY_CHOICES, null=True)
completed = models.BooleanField(default=False)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
category = models.ManyToManyField(Category)
def __str__(self):
return self.description
View
def todo_listview(request):
template_name = "todos/listview.html"
context = {
"todos": get_users_todos(user=request.user),
"categories": Category.objects.all(),
}
return render(request, template_name, context)
CodePudding user response:
You can prefetch the user's Todo
s, with:
from django.db.models import Prefetch
def todo_listview(request):
template_name = 'todos/listview.html'
context = {
'categories': Category.objects.prefetch_related(
Prefetch('todo_set', queryset=get_users_todos(user=request.user), to_attr='user_todos')
)
}
return render(request, template_name, context)
and then render this with:
Display each category
{% for category in categories %}
<h2>{{ category.name }}</h2>
{% for todo in category.user_todos %}
<p>{{ todo.description }}</p>
{% endfor %}
{% endfor %}
Since there is a many-to-many field between Category
and Todo
, it is possible that the same Todo
will be printed multiple times: once per category.
Note: The documentation advises to use the
AUTH_USER_MODEL
setting [Django-doc] overget_user_model()
[Django-doc]. This is safer, since if the authentication app is not yet loaded, the settings can still specify the name of the model. Therefore it is better to write:from django.conf import settings class Todo(models.Model): # … user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE )