I have a Django app where users can create their lists and add to-dos. I want to add a new page which will show to-dos that had due dates. Like, in the page, there will be a section called "Earlier" which was feature tasks with missed due dates. Other sections would be "Today", "Tomorrow" and "Later on". Let me show my view class and HTML code now and explain my problem.
Class based view to handle this page:
class ToDoNextUpView(LoginRequiredMixin, ListView):
model = ToDo
template_name = "ToDo/next_up.html"
ordering = ["-due_date"]
context_object_name = "todos"
def get_queryset(self):
query_set = []
for todo in ToDo.objects.filter(creator=self.request.user, is_checked=False):
if todo.due_date is not None:
query_set.append(todo)
return query_set
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
today = datetime.datetime.now(datetime.timezone.utc)
tomorrow = today + datetime.timedelta(days=1)
todos_earlier = []
todos_today = []
todos_tomorrow = []
todos_later = []
for todo in ToDo.objects.filter(creator=self.request.user, is_checked=False):
if todo.due_date is not None:
if todo.due_date.day == today.day and todo.due_date.month == today.month and todo.due_date.year == today.year:
todos_today.append(todo)
elif todo.due_date.day == tomorrow.day and todo.due_date.month == tomorrow.month and todo.due_date.year == tomorrow.year:
todos_tomorrow.append(todo)
elif todo.due_date < today:
todos_earlier.append(todo)
elif todo.due_date > tomorrow:
todos_later.append(todo)
context["todos_earlier"] = todos_earlier
context["todos_today"] = todos_today
context["todos_tomorrow"] = todos_tomorrow
context["todos_later"] = todos_later
return context
And this is next_up.html
{% extends "ToDo/base.html" %}
{% block content %}
{% load crispy_forms_tags %}
{% if todos_earlier %}
<center><h1 style="font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif; font-size: 10ch; background-color: royalblue;">Earlier</h1></center>
<br>
{% for todo in todos_earlier %}
<article class="content-section">
<div class="media-body full-content">
<h2>
<button onclick="location.href='{% url 'todo-check' todo.pk %}'" class="btn btn-outline-success">
<i class="fa fa-check"></i>
</button>
<a style="overflow: hidden; text-overflow: ellipsis;" href="{% url 'todo-detailed' todo.title todo.pk %}" class="article-title"> {{ todo.title }}</a>
<button data-toggle="modal" data-target="#exampleModalCenter{{ todo.pk }}" style="float: right;" class="btn btn-outline-danger">
<i class="fas fa-trash"></i>
</button>
{% if not todo.important %}
<button style="float: right; margin-right: 5px;" onclick="location.href='{% url 'todo-toggle-important' todo.pk %}'"
type="submit" class="btn btn-secondary">
<span aria-hidden="true"><i class="fas fa-star"></i></span>
</button>
{% else %}
<button style="float: right; margin-right: 5px;" onclick="location.href='{% url 'todo-toggle-important' todo.pk %}'"
type="submit" class="btn btn-warning">
<span aria-hidden="true"><i class="fas fa-star"></i></span>
</button>
{% endif %}
</h2>
<h3 style="color:red">
Was due on: {{ todo.due_date|date:"F d" }}
</h3>
</div>
</article>
{% endfor %}
{% endif %}
{% if todos_today %}
<center><h1 style="font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif; font-size: 10ch; background-color: royalblue;">For Today</h1></center>
<br>
{% for todo in todos_today %}
<article class="content-section">
<div class="media-body full-content">
<h2>
<button onclick="location.href='{% url 'todo-check' todo.pk %}'" class="btn btn-outline-success">
<i class="fa fa-check"></i>
</button>
<a style="overflow: hidden; text-overflow: ellipsis;" href="{% url 'todo-detailed' todo.title todo.pk %}" class="article-title"> {{ todo.title }}</a>
<button data-toggle="modal" data-target="#exampleModalCenter{{ todo.pk }}" style="float: right;" class="btn btn-outline-danger">
<i class="fas fa-trash"></i>
</button>
{% if not todo.important %}
<button style="float: right; margin-right: 5px;" onclick="location.href='{% url 'todo-toggle-important' todo.pk %}'"
type="submit" class="btn btn-secondary">
<span aria-hidden="true"><i class="fas fa-star"></i></span>
</button>
{% else %}
<button style="float: right; margin-right: 5px;" onclick="location.href='{% url 'todo-toggle-important' todo.pk %}'"
type="submit" class="btn btn-warning">
<span aria-hidden="true"><i class="fas fa-star"></i></span>
</button>
{% endif %}
</h2>
<h3 style="color:blue">
Due today
</h3>
</div>
</article>
{% endfor %}
{% endif %}
{% if todos_tomorrow %}
<center><h1 style="font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif; font-size: 10ch; background-color: royalblue;">For Tomorrow</h1></center>
<br>
{% for todo in todos_tomorrow %}
<article class="content-section">
<div class="media-body full-content">
<h2>
<button onclick="location.href='{% url 'todo-check' todo.pk %}'" class="btn btn-outline-success">
<i class="fa fa-check"></i>
</button>
<a style="overflow: hidden; text-overflow: ellipsis;" href="{% url 'todo-detailed' todo.title todo.pk %}" class="article-title"> {{ todo.title }}</a>
<button data-toggle="modal" data-target="#exampleModalCenter{{ todo.pk }}" style="float: right;" class="btn btn-outline-danger">
<i class="fas fa-trash"></i>
</button>
{% if not todo.important %}
<button style="float: right; margin-right: 5px;" onclick="location.href='{% url 'todo-toggle-important' todo.pk %}'"
type="submit" class="btn btn-secondary">
<span aria-hidden="true"><i class="fas fa-star"></i></span>
</button>
{% else %}
<button style="float: right; margin-right: 5px;" onclick="location.href='{% url 'todo-toggle-important' todo.pk %}'"
type="submit" class="btn btn-warning">
<span aria-hidden="true"><i class="fas fa-star"></i></span>
</button>
{% endif %}
</h2>
<h3 style="color:green">
Due tomorrow
</h3>
</div>
</article>
{% endfor %}
{% endif %}
{% if todos_later %}
<br>
<center><h1 style="font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif; font-size: 10ch; background-color: royalblue;">Coming up later</h1></center>
<br>
{% for todo in todos_later %}
<article class="content-section">
<div class="media-body full-content">
<h2>
<button onclick="location.href='{% url 'todo-check' todo.pk %}'" class="btn btn-outline-success">
<i class="fa fa-check"></i>
</button>
<a style="overflow: hidden; text-overflow: ellipsis;" href="{% url 'todo-detailed' todo.title todo.pk %}" class="article-title"> {{ todo.title }}</a>
<button data-toggle="modal" data-target="#exampleModalCenter{{ todo.pk }}" style="float: right;" class="btn btn-outline-danger">
<i class="fas fa-trash"></i>
</button>
{% if not todo.important %}
<button style="float: right; margin-right: 5px;" onclick="location.href='{% url 'todo-toggle-important' todo.pk %}'"
type="submit" class="btn btn-secondary">
<span aria-hidden="true"><i class="fas fa-star"></i></span>
</button>
{% else %}
<button style="float: right; margin-right: 5px;" onclick="location.href='{% url 'todo-toggle-important' todo.pk %}'"
type="submit" class="btn btn-warning">
<span aria-hidden="true"><i class="fas fa-star"></i></span>
</button>
{% endif %}
</h2>
<h3 style="color:seagreen">
Due on: {{ todo.due_date|date:"F d" }}
</h3>
</div>
</article>
{% endfor %}
{% endif %}
{% endblock content %}
As you can see, I have written almost the exact same HTML code for every one of those sections. Although this technically works but I would never be able to live with myself. I have to write those check buttons four times, star buttons four times and everything else four times. This cannot be good.
Also, in my View, I have made some sloppy coding where I checked the date, month and year which didn't seem right. But I am aware that checking only the day is not good since same days can of be different months. And to be clear, these are DateTime objects so I cannot just equal them since the precise seconds won't match. But I guess this could still be okay. My main question here is what changes should I bring about in my HTML and Python code so that I can display all the sections within a single for loop (or maybe nested loops but I don't want to four same code four times).
Thanks.