I want to annotate a datetime field to a queryset using timedelta and F objects
Example:
Model.objects.annotate(end_time=F('start_time')+timedelta(minutes=F('meeting_duration')))
Here I have a field "start_time" and "meeting_duration" in my table and I want to calculate and annotate an end_time using datetime.timedelta
And thereafter filter the queryset using the annotated field.
queryset.filter(end_time__gte=self.end_time)
Now I get this error:
TypeError: unsupported type for timedelta minutes component: F
Related
I have a "startTime" field in my model which contains timestamp.I want to get a list with count of only hour from that stamp.I mean my code should be able convert and get only hour from the timestamp and count the number of occurance of each hour.I tried doing
datetime.datetime.fromtimestamp(int(<timestamp>)).strftime(\'%H\'))
this thing returns only hour from a timestamp but when i tried incorporating it in the queryset..it failed..this is what i tried in my views.py
timehour = InteractionWith.objects \
.values('startTime')\
.annotate(times=Count('datetime.datetime.fromtimestamp(int("startTime")).strftime(\'%H\'))'))
You can annotate the queryset with ExtractHour [Django-doc]:
from django.db.models import Count
from django.db.models.functions import ExtractHour
timehour = InteractionWith.objects.values(
hour=ExtractHour('startTime')
).annotate(
times=Count('pk')
).order_by('hour')
I have a model whose fields are datetimefields start_time and end_time
I want to display on the API- start_time, end_time and the difference between them
However, I don't want to use for or while loop to achieve this because it is too slow
How can I get the difference on the API without looping
You can annotate the queryset with the difference, and then use an ExpressionWrapper to convert this to a DurationField, and thus obtain a timedelta objects:
from django.db.models import DurationField, ExpressionWrapper, F
MyModel.objects.annotate(
time_diff=ExpressionWrapper(
F('end_time')-F('start_time'),
output_field=DurationField()
)
)
The MyModels that arise from this queryset will thus have an extra attribute time_diff that is a timedelta field containing the difference between end_time, and start_time.
I am pretty new to django and haven't been able to find a way to get the elapsed time between two DateTimeFields and save it to another model.
from django.db import models
class Timesheet(models.Model):
startTime = models.DateTimeField(auto_now_add=True)
endTime = models.DateTimeField(blank=True, null=True)
duration = models.DateTimeField(endTime - startTime)
def _str_(self):
return self.startTime
How can I make duration = endTime - startTime?
I am also using a PostgreSQL database.
I wouldn't use a dedicated model field for the duration.
I would use a property on the model instead for the same functionality.
Something like:
#property
def duration(self)
return self.end_time - self.startime
Lucas has a good idea of using an annotation, but if you have a Timesheet instance somewhere that didn't come from that object manager and was not previously annotated, you would have to do a separate database hit to actually annotate it.
This property is used as such:
some_timesheet_instance.duration
Use annotate() to compute the duration field at query time for each object in the queryset
from django.db.models import F, ExpressionWrapper, fields
timesheets = Timesheet.objects.annotate(
duration=ExpressionWrapper(
F('endTime') - F('startTime'),
output_field=fields.DurationField()
)
)
timesheets[0].duration # datetime.timedelta(0, 722, 18373)
Is possible perform another queryset methods over annotations like filter(), order_by(), aggregate(), etc.
timesheets.order_by('-duration')
timesheets.aggregate(Avg('duration')) # {'duration__avg': datetime.timedelta(0, 26473, 292625)}
duration = timesheet.end_time - timesheet.start_time
When you substract two datetime instances you don't get another datetime instance but a timedelta instace, which is just the days, seconds and microseconds difference between the two datetimes. You can't store a timedelta in a DateTimefield, but you can use an IntegerField, for example:
days_in_seconds = duration.days * 86400 # days difference by seconds in a day
duration_in_seconds = duration.seconds + days_in_seconds # duration in seconds
When you want to access the duration as timedelta you just do:
import datetime
duration = datetime.timedelta(seconds=timesheet.duration)
You can also store it as FloatField as suggested in this question.
I want to send an email to users who haven't activated their accounts every 120 days. I'm using a DateTimeField for their created attribute.
How can I retrieve a queryset of users for whom created % 120 == 0?
Here's what I'm trying, using annotate and F objects:
members = Member.objects.annotate(
days_old=(datetime.datetime.now() - F('created'))
)
members = members.annotate(modulo_days=F('days_old') % 120)
members = members.filter(modulo_days=0)
...but this returns the errors:
TypeError: expected string or buffer
ProgrammingError: operator does not exist: interval % integer
How can I retrieve this queryset looking for the modulo of a timestamp on a Django model?
Another way of doing a queryset that could work for you:
from datetime import timedelta
from datetime import datetime
to_compare_datetime = datetime.now() - timedelta(days=180)
members = Member.objects.filter(account_activated=False, created__year=to_compare_datetime.year, created__month=to_compare_datetime.month, created__day=to_compare_datetime.day)
I'm supposing that your Member model has a field account_activated, and that the created field is a DateTimeField. Hope this can help you :)
I have the model
class Item(models.Model):
inicio = models.DateTimeField()
When I try to make this query:
itens = Item.objects.filter(inicio__hour__gte=6)
It returns me:
FieldError Unsupported lookup 'hour' for DateTimeField or join on the field not permitted.
How can I make this query?
Heads up, this should work as of Django 1.9
Event.objects.filter(timestamp__hour=23)
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)
You need to filter using a timedelta:
from datetime import datetime, timedelta
five_hours_ago = datetime.now() - timedelta(hours=5)
items = Item.objects.filter(inicio__lt=five_hours_ago)
You can always specify an exact datetime and then subtract 5 hours from it if you don't want 5 hours from the current datetime.
To the best of my knowledge, and according to the documentation, you can only do an exact lookup on an hour, minute or second.