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.

Antworten:


161

F Objekte.

from django.db.models import F
stale_activities = Activity.objects.filter(updated__gte=F('added_toSolr_date')) 

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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.