Search code examples
pythondjangosqlitemodelpython-datetime

Comparing timezone.now() in views.py to DateTimeField in models.py


I would like to create a To-Do list in which I can schedule date and time of each task. My goal is to get some sort of response whenever the supplied datetime is equal to the current time. For example I scheduled Do laundry for Monday at 6pm on a Saturday evening. Two days later (on Monday at 6pm) I would like to get a notification that I should Do laundry.

Notice that the key idea can be found in the index() function in views.py in the first rows including the if-statement.

Here is my code: urls.py

from django.urls import path

from . import views

urlpatterns = [
    path("", views.index, name="index"),
    path("<int:aufgabenzettel_id>", views.details, name="details"),
    path("add/", views.add, name="add"),
    path("delete/<int:aufgabenzettel_id>", views.delete, name="delete"),
    path("edit/<int:aufgabenzettel_id>", views.edit, name="edit"),
    path("update/<int:aufgabenzettel_id>", views.update, name="update")
]

models.py

from django.db import models

# Create your models here.
class Aufgabenzettel(models.Model):
    Aufgabeselbst = models.CharField(max_length=64)
    Datum = models.DateTimeField(auto_now_add=True)
    Geplant = models.DateTimeField(auto_now_add=False, auto_now=False)

    def __str__(self):
        return f"{self.Aufgabeselbst}"

views.py (the important part can be found in the index function in the first rows including the if-statement)

from django.db.models.fields import DateTimeField
from django.http.response import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django.utils import timezone
from datetime import datetime

from .models import Aufgabenzettel

# Create your views here.

def index(request):
    now = timezone.now()
    Aufgaben_items = Aufgabenzettel.objects.all().order_by("-Geplant") #arrange objects in the correct order
    for Aufgabenzettel.Geplant in Aufgaben_items: #run through the loop and...
        if Aufgabenzettel.Geplant == now: #...search for items in the database where the scheduled time ("Geplant" from "Aufgabenzettel" in models.py) is equal to the current time
            return render (request, "aufgabenzettel/add.html") #response in any way e.g. by returning the add.html 
    return render(request, "aufgabenzettel/index.html", {
        "Aufgabenliste":Aufgabenzettel.objects.all(), #currently not used
        "Aufgaben_items":Aufgaben_items
    })

def details(request, aufgabenzettel_id):
    aufgabenzettel = Aufgabenzettel.objects.get(pk=aufgabenzettel_id)
    creationDate = aufgabenzettel.Datum
    dueDate = aufgabenzettel.Geplant
    return render(request, "aufgabenzettel/details.html", {
        "details":aufgabenzettel,
        "creationDate": creationDate,
        "dueDate":dueDate
    })

def add(request):
    addDatum = timezone.now()
    if request.method == "POST":
        Aufgabe = request.POST["Hinzufügen"]
        geplantes_datum = request.POST["DatumFeld"]
        Aufgabenzettel.objects.create(Aufgabeselbst=Aufgabe , Datum=addDatum, Geplant=geplantes_datum) #Aufgabenname und Aufgabendatum erstellen
        return HttpResponseRedirect(reverse("index"))
    return render(request, "aufgabenzettel/add.html")

def delete(request, aufgabenzettel_id):
    aufgabenzettel = Aufgabenzettel.objects.get(pk=aufgabenzettel_id)
    aufgabenzettel.delete()
    return HttpResponseRedirect(reverse("index"))

def edit(request, aufgabenzettel_id):
    aufgabenzettel = Aufgabenzettel.objects.get(pk=aufgabenzettel_id)
    return render(request, "aufgabenzettel/edit.html", {
        "details":aufgabenzettel
    })

def update(request, aufgabenzettel_id):
    if request.method == "POST":
        Aufgabe = Aufgabenzettel.objects.get(pk=aufgabenzettel_id)
        Aufgabe.Aufgabeselbst = request.POST["Bearbeiten"]
        Aufgabe.save()
        return HttpResponseRedirect(reverse("index"))
    return render(request, "aufgabenzettel/edit.html")

index.html

{% extends "aufgabenzettel/layout.html" %}

{% block body %}
<h1 id="MeineAufgaben">Meine Aufgaben</h1>
    <table>
        {% for Aufgabeselbst in Aufgaben_items %}
            <tr>
                <td>
                    <a href="{% url 'details' Aufgabeselbst.id %}"> 
                        {{ Aufgabeselbst }}
                    </a>
                </td>
                <td>
                    <form action="{% url 'delete' Aufgabeselbst.id %}" method="post">
                        {% csrf_token %}
                    <button type="submit"  id="löschenbtn">Löschen</button>
                </form>
                </td>
                <td>
                    <form action="{% url 'edit' Aufgabeselbst.id %}" method="post">
                        {% csrf_token %}
                    <button type="submit" value="{{ details }}" class="bearbeitenbtn">Bearbeiten</button>
                    </form>
                </td>
            </tr>
        {% endfor %}
    </table>
    <h2>
        <a href="{% url 'add' %}" id="neuebtn">Neue Aufgabe erstellen</a>
    </h2>
{% endblock %}

add.html

{% extends "aufgabenzettel/layout.html" %}

{% block body %}
    <h1>Füge eine neue Aufgabe hinzu!</h1>
    <form action="{% url 'add' %}" method="post">
        {% csrf_token %}
        <input type="text" name="Hinzufügen" placeholder="Neue Aufgabe">
        <input type="datetime-local" name="DatumFeld">
        <button type="submit" id="Hinzufügen">Hinzufügen</button>
    </form>
{% endblock %}

details.html

{% extends "aufgabenzettel/layout.html" %}

{% block body %}
    <h1>{{ details }}</h1>
    <h3>Erstellt: {{ creationDate }}</h3>
    <h2>Geplant: {{ dueDate }}</h2>
    <a href="{% url 'index' %}">Zurück zu Aufgabe</a>
{% endblock %}

edit.html

{% extends "aufgabenzettel/layout.html" %}

{% block body %}
    <h2>Bearbeite deine Aufgabe "{{ details }}"</h2>
    <form action="{% url 'update' details.id %}" method="post">
    {% csrf_token %}
        <input type="text" name="Bearbeiten" value="{{details}}">
        <button type="submit" class="bearbeitenbtn">Bearbeiten</button>
    </form>
    <a href="{% url 'index' %}">Zurück zu Aufgabe</a>
{% endblock %}

layout.html

{% load static %}
<!DOCTYPE html>
<html lang="de">
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Aufgabenzettel</title>
        <link rel="stylesheet" href="{% static '/css/main.css' %}">
    </head>
    <body>
        {% block body %}
        {% endblock %}
    </body>

</html>

I don't get an Error or anything but the code is not running as expected. I just want the index function to loop through each element in the database Aufgabenzettel in models.py and if it detects an element where the scheduled time corresponds with the current time some sort of action (in this case a redirect to add.html is ecpected) should happen. However I don't get any such response...

Like always, I appreciate every kind of solution or help!


Solution

  • The code in your view isn't being triggered because datetimes have microsecond accuracy.

    You could solve this a number of ways. One option is to check if any item has occurred in the last hour:

    from datetime import timedelta
    
    def index(request):
        now = timezone.now()
        in_the_past = now - timedelta(hours=1)
        items_exist = Aufgabenzettel.objects.filter(
            Geplant__gt=in_the_past,
            Geplant__lt=now
            ).exists()
        if items_exist
            return render (request, "aufgabenzettel/add.html")
        return render(request, "aufgabenzettel/index.html", {
            "Aufgabenliste":Aufgabenzettel.objects.all(), #currently not used
            "Aufgaben_items":Aufgaben_items
        })
    

    Another option might involve adding a new field to your model to indicate when a task has been completed:

    class Aufgabenzettel(models.Model):
        Aufgabeselbst = models.CharField(max_length=64)
        Datum = models.DateTimeField(auto_now_add=True)
        Geplant = models.DateTimeField(auto_now_add=False, auto_now=False)
        is_complete = models.BooleanField(default=False)
    

    Then your view can be updated to trigger whenever a task occurred in the past and hasn't yet been marked:

    def index(request):
        now = timezone.now()
        items_exist = Aufgabenzettel.objects.filter(
            is_complete=False,
            Geplant__lt=now
            ).exists()
        if items_exist
            return render (request, "aufgabenzettel/add.html")
        return render(request, "aufgabenzettel/index.html", {
            "Aufgabenliste":Aufgabenzettel.objects.all(), #currently not used
            "Aufgaben_items":Aufgaben_items
        })
    

    The simplest way to have the condition checked regularly is to have your browser automatically reload the page. You can do this by adding the following tag to the <head> section of your template:

    <meta http-equiv="refresh" content="120">