I'm wondering if it is possible to use Django on a database of transaction to get all transaction that happened on a(ll) Monday(s) between 10 and 11.
For completeness here is the model definition:
class P1data(models.Model):
date_time = models.DateTimeField(auto_now_add=True, db_index=True)
price = models.DecimalField(max_digits=40, decimal_places=12)
volume = models.DecimalField(max_digits=40, decimal_places=12)
Use the week_day and hour lookups:
P1data.objects.filter(date_time__week_day=2, date_time__hour__range=(10, 11))
UPDATE: If hour lookup doesn't support range then try to use the combination of lte/gte:
P1data.objects.filter(date_time__week_day=2,
date_time__hour__gte=10,
date_time__hour__lte=11)
Related
I have a recurring events application, each event can have multiple recurrence patterns (RFC5545), a date can be in different recurrence patterns so I have added an autofield integer to prioritize the most recently added recurrences, each recurrence pattern has a max seat capacity.
So far so good the problem starts when I need to check all the dates that have seats available for the next 365 days:
I would have to check each date against a recurrence rule/pattern and finding that date get the capacity associated with the recurrence.
maybe an example pseudocode is better understood than my English.
ex.:
reseved = "info with the number of person by each date reserved"
patterns = {
0:["RRULE:FREQ=DAILY;", "max 10 person"],
1:["RRULE:FREQ=MONTLY;UNTIL=2021-10-10", "max 15 person"],
2:["RRULE:FREQ=DAILY;UNTIL=2021-06-15", "max 25 person"]
}
patterns_ordered = patterns.order_by["index"]
date = "2021-01-01"
last_date = "2021-01-01" + 365 days
while date < laste_date:
for rule in patterns_ordered:
If date in rule and rule.capacity > number_reserved in date:
save date in array with it's availibility.
this is very costly in terms of performance, I have tried to check month after month while the user is browsing a calendar. it is very expensive and the server is overloaded with the number of ajax calls.
more information about my model class:
class Event(models.Model):
e_name = CharField
e_description = TexField
class EventRecurrence(models.Model):
event = ForeignKey(to=Event)
rfc_pattern = CharField #with rfc ical validation
max_guest = PositiveIntegerField
index = OrderedPositiveIntegerField # an autofield based in event
clas Reservation(models.Model):
date = DateField # date reserved
passengers = PositiveIntegerField
amount = DecimalField
event = ForeignKey(to=Event)
...........
I have the following model on my postgresql database:
class UrlXML(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True)
url = models.TextField()
is_active = models.BooleanField(default=True, db_index=True)
run_last_time = models.DateTimeField(blank=True, null=True)
run_frequency = models.IntegerField(default=24)
Every hour I need to get from database url that need to be downloaded based when on my current time and if the last time it ran was higher then the frequency.
I manage to create the raw query, but I can't manage to create it in Django Queryset.
Here is the following query:
select (run_last_time + INTERVAL '1 hours' * run_frequency), run_frequency, NOW(), run_last_time from urlxml where is_active=True and (run_last_time + INTERVAL '1 hours' * run_frequency) <= NOW();
Example:
Current time is 2017-04-03 11:00:00
I have two url in database:
Url A: Ran last time 2017-04-03 08:00:00 and its frequency is 6 hours
Url B: Ran last time 2017-04-02 11:00:00 and its frequency is 24 hours
When I execute the function at 2017-04-03 11:00:00 (within the margin of + and - 30 minutes), it must bring me the Url B only, 'cause the last time it ran was 24 hours ago.
I managed to find a solution using the extra in the Queryset.
Here it is:
UrlXML.objects.filter(is_active=True).extra(
where={"run_last_time + INTERVAL '1 hours' * run_frequency <= NOW()"}
)
I don't know if this is the best way to do this, but is the only one I manage to find.
If there are better ways to do it, I'm open to suggestions.
If you were to change your model slightly, you could use Query Expressions.
# models.py
class UrlXML(models.Model):
...
run_frequency = models.DurationField(default=timedelta(hours=24))
UrlXML.objects \
.annotate(expires=ExpressionWrapper(
F('run_last_time') + F('run_frequency'),
output_field=DateTimeField())) \
.filter(expires__lte=datetime.now())
This solutions is also a bit more robust, as you can use datetime.timedelta instead of hours only.
I am making a scheduler in Django and having issues filtering my events for the weekly calendar view. The calendar supports multi-day events, and my current filter doesn't work with this weekly view.
Here is my model:
class Event(models.Model):
title = models.CharField(max_length=40)
start = models.DateTimeField()
end = models.DateTimeField()
description = models.TextField()
all_day = models.BooleanField(default=False)
recuring = models.BooleanField(default=False)
recuring_end = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return '/cab/event/%i/' % self.id
and I'm trying to filter the events that occur during a given week. For single day events I do something like.
events = Event.objects.order_by('start').filter(Q(start__gte=monday) | Q(end__lte=sunday))
This works to retrieve all single day events that occur during the week. It also works for multi-day events that either start or stop during the given week. The issue is retrieving objects that start before and finish after the week, but do span the week.
My idea is to try and filter out any event spanning longer than 9 days (ie. would start Sunday of prior week and finish Monday of next week) since I know these are rare and wont completely destroy performance. I want to do this without specifying a date range as this is not dynamic.
To try and minimise the performance impact I was trying to use F expressions to evaluate the duration of the event with the start and end of the event. My first idea was to do something like:
my_events = Event.objects.order_by('start').filter(Q(start__gte=monday) | Q(end__lte=sunday) | Q( (F('end_day') - F('start_day')) >= 9 ) )
but I get error 'bool' object is not iterable
also tried:
my_events = Event.objects.order_by('start').filter(Q(start__gte=monday) | Q(end__lte=sunday) | Q( (F('end_day') - F('start_day')) >= datetime.timedelta(days=9) ) )
but get can't compare datetime.timedelta to ExpressionNode
Anyone have incite as how to do such a thing?
from datetime import timedelta
Event.objects.filter(end__gt=F('start') + timedelta(days=9))
Documentation has example.
UPDATE:
Events, that span more than 9 days AND (start later than Monday OR end sooner than Sunday), ordered by start.
(Event.objects
.filter(end__gt=F('start') + timedelta(days=9),
Q(start__gte=monday) | Q(end__lte=sunday))
.order_by('start'))
Just the warning to #https://stackoverflow.com/users/4907653/f43d65
's answer, that last query lookups with Q objects might be invalid.
Reference to docs
Lookup functions can mix the use of Q objects and keyword arguments. All arguments provided to a lookup function (be they keyword arguments or Q objects) are “AND”ed together. However, if a Q object is provided, it must precede the definition of any keyword arguments. For example:
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who',)
… would be a valid query, equivalent to the previous example; but:
# INVALID QUERY
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
… would not be valid.
This is driving me crazy. I've used all the lookup_types and none seem to work.
I need to select an object that was created two weeks ago from today.
Here's what I've got:
twoweeksago = datetime.datetime.now() - datetime.timedelta(days=14)
pastblast = Model.objects.filter(user=user, created=twoweeksago, done=False)
The model has a created field that does this: created = models.DateTimeField(auto_now_add=True, editable=False)
But my query isn't returning everything. Before you ask, yes, there are records in the db with the right date.
Can someone make a suggestion as to what I'm doing wrong?
Thanks
DateTimeField is very different from DateField, if you do
twoweeksago = datetime.datetime.now() - datetime.timedelta(days=14)
That is going to return today's date, hour, minute, second minus 14 days, and the result is going to include also hours minutes seconds etc. So the query:
pastblast = Model.objects.filter(user=user, created=twoweeksago, done=False)
Is going to find for a instance was created just in that exact time, If you only want to care about the day, and not hours, minutes and seconds you can do something like
pastblast = Model.objects.filter(user=user, created__year=twoweeksago.year, created__month=twoweeksago.month, created__day=twoweeksago.day, done=False)
Check the django docs:
https://docs.djangoproject.com/en/1.4/ref/models/querysets/#year
I have this model:
class Person(models.Model):
city = models.CharField(max_length=20, blank=True)
added_date = models.DateField(default=datetime.date.today)
I want to create a template/view that has a table of months and the number of people added that month (ie, 5 in january, 10 in february, 8 in march, etc.). I have a similar table for all the people from a each city using:
cities = Patient.objects.values('city').annotate(city_count=Count('city')).order_by('-city_count')
I don't know how to do that for my months table. I could filter for a particular month, then count all. But then I'd need to run that through a loop over every month, which would be multiple database hits. I don't want to do that.
Is there a way to do this without writing sql and just using django's api?
Its a very old thread, but i guess I'll answer in case someone else ended up here looking for a solution.
The solution is for Django 1.10+ using the ExtractMonth function, for more detail visit official documentation
First you have to import ExtractMonth, like
from django.db.models.functions import ExtractMonth
Then using your Persons model, the code will be like this
personsMonthlyData = Person.objects.annotate(month=ExtractMonth('added_date')).values('month').annotate(count=Count('id')).order_by('month')
personsMonthlyData will output something like this
[{month: 1, count: 3}, {month: 2: count: 1}]
where month represent the month number e.g. 1 for January and 2 for February and the count against each month is assigned to the count item.
I hope this helps.
The fact that most DBs have such a perfect way of doing this with a GROUP BY query that has no analog in Django AFAIK would lead me to drop into SQL to do this. I did a google search for "django sql" and turned up this post by Doug Hellman on this exact problem: http://blog.doughellmann.com/2007/12/using-raw-sql-in-django.html. I would use that as a starting point for getting your month counts into Django.