Wpis z mikrobloga

#python #django

Mirki, chcę na serwerze odpalać periodic task, który co x minut będzie odpytywał model i sprawdzał czy są w nim maile do wysłania.

Całą resztę ogarnąłem ale mam problem do stworzenia odpowiedniego query w managerze, który ma działać w następujący sposób:

1) w managerze określam aktualną datę(currentdate)
2) w zależności od rodzaju emaila, wybieram okres, po którym ma zostać wysłany(delta) - ponieważ te okresy są dynamiczne, musi być to liczone od aktualnej daty)
3) jeżeli minął określony przeze mnie okres, queryset ma zwrócić te obiekty

Poniżej wrzucam prove of concept, które wywala się oczywiście na tym kawałku
((current
date - F('created_at')).seconds
dalej wywali się też na delta > 0 ale tak jak mówię, to tylko prove of concept

delta = 60 * 1 * 5
currentdate = timezone.now()
qs = self.annotate(passed=((current
date - F('created_at')).seconds // delta > 0)).filter(passed=True)

nie wiem czy nie próbuję tego przekombinować trochę, anyway, za każdą poradę będę wdzięczny
  • 12
@maledorak: teraz to oczywisty błąd,
AttributeError: 'CombinedExpression' object has no attribute 'seconds'
((currentdate - F('createdat')).seconds nie ewaluuje się do datetime.timedelta object ale do CombinedExpression

kombinowałem też z ExpressionWrapper ale bez efektu
@michael93pl: obliczanie delty wynieś wyżej, po to jest datetime.timedelta
delta = 60 * 1 * 5
sendafter = timezone.now() + datetime.timedelta(seconds=delta)

i wtedy robisz porównanie currentdate z send
after, który jest oiektem datetime i nie musisz nic kombinować z sekundami
@maledorak źle to chyba opisałem
sendafter nic mi nie da jako obiekt datetime, ponieważ musze porownac createdat(DateTimeField w modelu z autoaddnow) do czasu now() i czy minęło od created at 5 minut
@michael93pl

delta = 60 * 1 * 5
sendafter = timezone.now() - datetime.timedelta(seconds=delta)
self.filter(created
at_gte=sendafter)

test:
obiekt1.createdat = 12:00
obiekt2.created
at = 12:10

now = 12:12
sendafter = 12:12 - 3min = 12:09
self.filter(created
at_gte=sendafter) <--- ten filter zwroci tylko obiekt2, bo czas jego utworzenia jest większy niż send after.

poczytaj dokumentacje o filtrach:
https://docs.djangoproject.com/en/2.2/ref/models/querysets/#field-lookups
szczególnie o czasie

mam nadzieje że zrozumiałem o co Ci
@maledorak niestety trochę to źle opisałem, createdat nigdy nie będzie większe niż jakakolwiek data, przynajmniej nie o to chodzi
Muszę znaleźć ile wynosi różnica pomiędzy
now() a wartością w polu created
at i jeżeli wynosi więcej niż delta to zwrócić ten obiekt w qs

coś pokroju:
self.annotate(foo=(Sum(F('createdat) - currentdate)) ale obv lokalnie mam tylko sqllite, na którym agregacja przez Sum nie działa, a właśnie wychodzę i nie zdarze przepiąć
@krzysiek_pl celery już wykorzystuje
prze systemd śmiga mi proces co x minut, ktory wyciągać te obiekty z bazy i jeżeli mail jest już gotowy do wysłania do przekazuje buduje obiekt maila wraz z contextem i templatem, a następnie przekazuje go przez adapter to zewnętrznego dostawcy usługi wysyłania maili
Muszę tylko osiągnąć to, co przedstawia mój przykład ale ciągle nie wiem jak :/
@maledorak: taski celery moga sie lekko "mylic" choc nie powinno miec to znaczenia, sprawdzam jedynie okresy pomiedzy aktualnym czasem na serwerze, a momentem stworzenia obiektu na tym samym serverze, wiec nie powinno byc zadnych roznic ^^

idea byla taka, zeby maile wysylaly sie po wypelnieniu formularza tak dlugo(okresy x, y,z) az klient nie wypelni okreslonego warunku, ktorego stan zmieni sie dopiero wtedy, gdy zewnetrzny dostawca uslugi da mi o tym znac