So erstellen Sie einen Django-Abfragesatzfilter, der zwei Datumsfelder im selben Modell vergleicht

81

Ich habe versucht, eine Abfrage zu erhalten, bei der der Aktivitätsdatensatz in meinem Solr-Index veraltet ist. Ich möchte überprüfen, ob das Activity.updatedDatum in der Datenbank größer ist als das Activity.added_toSolr_datefür denselben Datensatz.

stale_activities_queryset = Activity.objects.filter(updated__gte = self.added_toSolr_date) 

Modell

class Activity(models.Model):
    # Last time entry / metric was updated in the Activity model database
    updated =  models.DateTimeField( verbose_name="CRUD date")
    # When it was added to Solr Index Date
    added_toSolr_date = models.DateTimeField(blank=True, null=True, verbose_name="Added to Solr Index Date")

Ich habe auf Django Query-Dokumente verwiesen: https://docs.djangoproject.com/de/1.4/ref/models/querysets/ Und Unit-Tests für Beispiele: https://github.com/django/django/blob/master/tests/ modeltests / or_lookups / tests.py

Auch hier auf Stackoverflow gesucht. Alle Beispiele verwenden ein eingegebenes Datum, anstatt zwei Datumsfelder im selben Modell zu vergleichen.

Carlos Ferreira
quelle

Antworten:

161

F Objekte.

from django.db.models import F
stale_activities = Activity.objects.filter(updated__gte=F('added_toSolr_date')) 
Yuji 'Tomita' Tomita
quelle
Vielen Dank! Wie haben Sie das entdeckt?
Carlos Ferreira
6
@CarlosFerreira, durch jahrelange tägliche Verwendung von Django. Ich kann nicht wirklich sagen wann.
Yuji 'Tomita' Tomita
schöne Lösung! fast die gleiche Frage gestellt
Ron
Vielen Dank! Ich habe danach gesucht!
Alex Santos
2
Dies scheint fehlzuschlagen, wenn eines der Daten NULL ist. Verwenden von Q zum Überprüfen auf Null oder Vergleichen und dennoch fehlschlagen. Auch wenn dies in MySQL nicht der Fall wäre, sieht dies sonst noch jemand?
Paul Kenjora
3

Die Lösung von Yuji Tomita hat leider nicht funktioniert.

Betrachten Sie ein Modell unten:

class list(models.Model):
    text = models.CharField(max_length=140)
    created = models.DateTimeField()
    modified = models.DateTimeField()

Abfragesatz:

my_list = todolist.objects.order_by('created').filter(created__gte=F('modified'))

Vorlage:

{% if my_list %}
{% for list in my_list %}
{{ list.text}}
{% endfor %}
{% else %}
<p>there is no list</p>
{% endif %}

Am Ende bekomme ich eine leere Liste, aber ich weiß, es ist nicht korrekt. Ich habe auch Folgendes in der Vorlage verwendet (ohne Queryset-Filter):

{% if list.created|date:'d m y h:i:s' == list.modified|date:'d m y h:i:s' %}

Es hat funktioniert, aber ich würde es vorziehen, eine elegantere Lösung zu sehen.

Sergey Krivoy
quelle
Beim schnellen Lesen sieht es so aus, als würden Sie zwei verschiedene Dinge in Ihrem Abfragesatzfilter und in unserem Vorlagencode tun. Im ersten Fall verwenden Sie 'gte' und im zweiten Fall verwenden Sie '=='. Erzielen die beiden deshalb nicht die gleichen Ergebnisse? Ich versuche herauszufinden, warum die Verwendung mydate__exact = F('my_other_date')in einer Abfrage nicht funktioniert, wenn 'my_other_date' selbst None ist.
Jenniwren
Ich hatte einen anderen Grund, warum es nicht funktionieren würde. Unter Verwendung django-extensions TimeStampedModelder createdund updatedgleich Zeitstempel auf die Millisekunde nach unten. Es gibt eine minimale Verzögerung. Meine schnelle Lösung bestand darin, es mit der Sekunde zu vergleichen.
Tschale