Issue
I have a datetime field in Django, and I want to filter this based on time. I don't care about the particular date, but I want to find all transactions before 7:30, for example.
I know I can filter by hour and minute such as:
Q(datetime__hour=7) & \
Q(datetime__minute=30)
However, this would find all transactions AT 7:30. You are also unable to apply gte or lte. i.e.
(Q(datetime__hour__lte=7) & \
Q(datetime__minute__lte=30)) | \
Q(datetime__hour__lt=7)
The only thing that appears to be a potential solution is to have many queries, such as:
(Q(datetime__hour=7) & \
(Q(datetime__minute=30) | \
Q(datetime__minute=29) | \
Q(datetime__minute=28) | \
....
Q(datetime__minute=2) | \
Q(datetime__minute=1) | \
Q(datetime__minute=0))) | \
Q(datetime__hour=6) | \
Q(datetime__hour=5) | \
Q(datetime__hour=4) | \
Q(datetime__hour=3) | \
Q(datetime__hour=2) | \
Q(datetime__hour=1) | \
Q(datetime__hour=0)
But this seems ridiculous.
Anyone have any ideas?
Solution
Just split the datetime field into a date and a time field. Than you can filter on time only:
from datetime import combine
class MyModel(models.Model):
start_date = models.DateField()
start_time = models.TimeField()
class Meta:
ordering = ['start_date', 'start_time']
def start_datetime(self):
return combine(self.date, self.time)
I added the Meta.ordering and start_datetime model method to show that this model can present data in the same way a model with a DateTimeField can.
Now you can filter on time:
objects = MyModel.objects.filter(start_time__lt=time(7, 30))
Update
If you have a established project and many queries depend on having a normal DateTime field. Splitting the datetime into a date and time fields come a cost: Rewriting queries threw out your project. There is an alternative: Only add a time field and leave the datetime field untouched. A save method can add the time based on datetime. The down side is that you have duplicated data in your db. The good thing it solves your problem with minimal effort.
class MyModel(models.Model):
start_datetime = models.DateTimeField()
start_time = models.TimeField(blank=True)
def save(self)
self.start_time = self.start_datetime.time
All existing queries will be the same as before and filter on time only:
objects = MyModel.objects.filter(start_time__lt=time(7, 30))
Answered By - allcaps
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.