2016-11-15 4 views
3

Ich muss Objekte älter als X Anzahl der Tage filtern. Ich weiß, diese Frage existiert hier: django filter older than day(s)?Django - Filter Objekte älter als X Tage

Aber ich versuche nicht, genau das zu tun, da die Anzahl der Tage, in meinem Fall im Modell lebt:

class Post(models.Model): 
    title = models.CharField(max_length=200) 
    description = models.CharField(max_length=500) 
    createdAt = models.DateTimeField(default=datetime.now, blank=True) 
    plan = models.ForeignKey(Plan) # This model has the number of days 

Dies ist die Abfrage, die ich so habe weit:

EDIT: änderte ich den days.plan Teil für the_post.plan.days Bedeutung, dass die Anzahl der Tage, die ich verwende plan Feld in jeder Post zu vergleichen ist.

Post.objects.filter(createdAt__lte=datetime.now() - timedelta(days=the_post.plan.days)) 

Notiere die plan.days Teil der Abfrage. Wie kann ich für diese Abfrage auf the_post.plan.days verweisen? Ist es möglich?

Antwort

2

Mit einem kleinen zwicken in Ihrem Plan-Modell, ist es in der Tat möglich, zu tun, was Sie wollen.

Zunächst müssen Sie Ihren Plan days Feld, das ist wahrscheinlich eine IntegerField, zu DurationField ändern.

Jetzt ist der Haken, dass wir ExpressionWrapper verwenden müssen, um genau das gleiche Ergebnis in Postgres zu erreichen, wie das Ergebnis in Python, wenn Sie den Plan in einer separaten Abfrage erhalten würden.

from django.db.models import F, ExpressionWrapper, DateTimeField 
from django.utils import timezone 

Post.objects.annotate(target_date=ExpressionWrapper(timezone.now() - F('plan__days'), output_field=DateTimeField())).filter(createdAt__lte=F('target_date')) 
+0

Hey @lucasnadalutti Das scheint die richtige Antwort zu sein, aber ich bekomme diesen Fehler zurück: 'ValueError: Nicht naive Datetime (tzinfo ist bereits gesetzt)' nicht sicher warum – danielrvt

+0

Ersetze 'datetime.now()' mit 'timezone .now() ', da es mit' from django.utils import timezone' importiert wird – lucasnadalutti

0

Für mich müssen Sie zuerst das Planobjekt greifen.

plan = Plan.objects.filter(...) 

und dann die Tage Referenz

Post.objects.filter(createdAt__lte=datetime.now() - timedelta(days=plan.days)) 
+0

Wie ist das anders aus, was die Frage enthält

Schließlich sollte Ihre Abfrage so etwas wie sein? – Brian

+0

Der Plan im Post-Modell bezieht sich auf eine andere Tabelle, so dass er nicht wissen konnte, was die Tage sind. im Beispiel bekomme ich zuerst den Plan, den ich brauche, und in der Planvariablen sind die Tage Variable (zum Beispiel 3). Dann können Sie die Posts für den gegebenen Plan finden, die Sie brauchen. – user2693928

+0

Das ist schon was die Frage tut; 'plan.days' hätte sonst' Post.plan.days' (was ein AttributeError ist) oder ähnliches gelesen. – Brian

1

Unter der Annahme, Postgres-Datenbank:

table_post = Post._meta.db_table 
table_plan = Plan._meta.db_table 

old_posts = Post.objects.select_related('plan')\ 
      .extra(where=["%s.created_at <= NOW() - INTERVAL '1 day' * %s.days" 
          % (table_post, table_plan)]) 
Verwandte Themen