Jak utworzyć filtr zestawu zapytań Django porównujący dwa pola daty w tym samym modelu

82

Próbuję uzyskać zapytanie, w którym rekord Aktywności jest nieaktualny w moim indeksie Solr. Chcę sprawdzić, czy Activity.updateddata w bazie danych jest większa niż data Activity.added_toSolr_datedla tego samego rekordu.

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

Model

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")

Odwołałem się do dokumentacji Django Query: https://docs.djangoproject.com/en/1.4/ref/models/querysets/ Oraz testy jednostkowe dla próbek: https://github.com/django/django/blob/master/tests/ modeltests / or_lookups / tests.py

Przeszukano także tutaj w Stackoverflow. Wszystkie przykłady używają wprowadzonej daty zamiast porównywać dwa pola daty w tym samym modelu.

Carlos Ferreira
źródło

Odpowiedzi:

162

Obiekty F.

from django.db.models import F
stale_activities = Activity.objects.filter(updated__gte=F('added_toSolr_date')) 
Yuji „Tomita” Tomita
źródło
Dzięki wielkie! Jak to odkryłeś?
Carlos Ferreira
6
@CarlosFerreira, przez lata codziennego używania django. Naprawdę nie mogę powiedzieć kiedy.
Yuji „Tomita” Tomita
fajne rozwiązanie! prawie wysłał to samo pytanie
Ron
Dzięki! Szukałem tego!
Alex Santos,
2
Wydaje się, że kończy się to niepowodzeniem, jeśli jedna z dat ma wartość NULL. Używanie Q do sprawdzania wartości null lub porównania i nadal kończy się niepowodzeniem. Nawet jeśli nie ma tego w MySQL, ktoś inny to widzi?
Paul Kenjora,
3

Rozwiązanie Yuji Tomita niestety nie zadziałało.

Rozważ poniższy model:

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

Queryset:

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

Szablon:

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

W końcu otrzymuję pustą listę, ale wiem, że nie jest poprawna. W szablonie wykorzystałem również następujące elementy (bez filtra queryset):

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

Udało się, ale wolałbym zobaczyć bardziej eleganckie rozwiązanie.

Sergey Krivoy
źródło
Na pierwszy rzut oka wygląda na to, że robisz dwie różne rzeczy w filtrze zestawu zapytań i kodzie naszego szablonu. W pierwszym przypadku używasz „gte”, aw drugim „==”. Czy to dlatego te dwa nie dają takich samych wyników? Próbuję dowiedzieć się, dlaczego używanie mydate__exact = F('my_other_date')w kwerendzie nie działa, gdy „moja_inna_data” ma wartość Brak.
jenniwren
Miałem inny powód, dla którego to nie zadziałało. Używając django-extensions TimeStampedModel, znaczniki czasu createdi są updatedrówne z dokładnością do milisekundy. Występuje minimalne opóźnienie. Moją szybką poprawką było po prostu porównanie tego z sekundą.
tschale