I got two models :
models.py
class Representation(models.Model):
datetime = models.DateTimeField()
show = models.ForeignKey(Show)
class Show(models.Model):
name = models.CharField(max_length=512)
and then I'd like to have the next 5 incoming shows, and the best i can do is a clever hack like that, but this just uses a ton of queries, and I'm sure there is a more pythonic way to do it
i=5
list_shows = set()
while (len(list_shows) < 5:
for rep in Representation.objects.filter(datetime__gt=datetime.now()).order_by('-datetime')[:i]:
list_shows.add(rep.show)
i+=1
if i>100:
break
I also tryed something like this :
from datetime import datetime
from django.db.models import Min
Show.objects.annotate(date=Min('representation__datetime')).filter(date__gte=datetime.now()).order_by('date')[:5]
But this doesn't take the case where a show already played yesterday but play against tonight.
Can you try this:
Show.objects.filter(representation_set__datetime__gt=datetime.now()).order_by('representation_set__datetime')[:5]
Related
i'm trying to give condition to an annotate field to return a BooleanField
class Employee(models.Model):
date_of_expire = models.DateTimeField()
my views.py
from django.db.models import Case,When,BooleanField
def lists(request):
lists = Employee.objects.annotate(is_expire=Case(When(
date_of_expire__lte=timezone.now()
),output_field=BooleanField())).order_by('-date_of_expire')
#others
but it doesnt work , still return all existing data even some of object's date_of_expire is less than current time
is there something else i should try please ?
as Mr #willem Van Onsem mentioned a link in the comment
from django.db.models import BooleanField,ExpressionWrapper,Q
lists = Employee.objects.annotate(is_expire=ExpressionWrapper(Q(date_of_expire__lte=timezone.now()),output_field=BooleanField()).order_by('-date_of_expire')
ExpressionWrapper
I want an "active_in" attribute as a timeframe. I assume that the DBMS is optimized for the postgresql tsrange field, and as such it is preferable to utilize the DateTimeRangeField rather than 2 separate fields for start_date and end_date.
Doing this I desire a default value for the field.
active_in = models.DateTimeRangeField(default=timezone.now+'-'+timezone.now+10YEARS)
Is my assumption about the DateTimeRangeField performance true?
Is there a smart solution be it creating a new; function,class or
simply manipulating the 2nd last digit?
My possible solutions:
Code using string manipulation:
active_in = models.DateTimeRangeField(default=timezone.now+'-'+timezone.now[:-2]+'30')
Code using custom function object: (adjusted from here: https://stackoverflow.com/a/27491426/7458018)
def today_years_ahead():
return timezone.now + '-' timezone.now() + timezone.timedelta(years=10)
class MyModel(models.Model):
...
active_in = models.DateTimeRangeField(default=today_years_ahead)
There's no need for string manipulation, as the documented Python type for this field is DateTimeTZRange.
I can't say I've ever used this field before, but something like this should work:
from psycopg2.extras import DateTimeTZRange
from django.utils import timezone
from datetime import timedelta
def next_ten_years():
now = timezone.now()
# use a more accurate version of "10 years" if you need it
return DateTimeTZRange(now, now + timedelta(days=3652))
class MyModel(models.Model):
...
active_in = models.DateTimeRangeField(default=next_ten_years)
Suppose I want to have a model like this:
from django.db import models
from django.contrib.postgres.fields import DateRangeField
class QueryRange(models.Model):
name = models.CharField('Name', max_length=50)
rsv = DateRangeField()
And in shell I create some objects like this:
obj1 = QueryRange.objects.create(name='John', rsv=('2016-06-01', '2016-06-10'))
obj2 = QueryRange.objects.create(name='Peter', rsv=('2016-07-05', '2016-07-10'))
obj3 = QueryRange.objects.create(name='Chris', rsv=('2016-07-12', '2016-07-15'))
How can I query the db by asking this question: Please check and see if the date i.e '2016-07-08' is occupied or not.
Something like this won't work:
from psycopg2.extras import DateRange
rng = DateRange('2016-07-08')
QueryRange.objects.filter(rsv__contains=rng)
I have implement the same scenario with two separate date fields (from_date and until_date) and works great (of course). I am just curious how can I benefit myself with the DateRangefield.
Cheers to all Djangonauts out there!
You're very close with your answer. When you're looking for the presence of a single date, use a date object directly:
from datetime import date
QueryRange.objects.filter(rsv__contains=date.today())
If you're using a date range to query, you're probably looking to see if there's any overlap:
rng = DateRange('2016-07-08', '2016-07-20')
QueryRange.objects.filter(rsv__overlap=rng)
Tested both examples to make sure they work.
I have the following models:
class Item(models.model):
price = models.floatField()
...
and :
class purchase(models.model):
user = models.ForeignKey(User)
item = models.ForeignKey(Item)
date = models.DateField()
I would like to make a query which will provide top 10 users who purchased the most in the last week .I would also like to have the Sum of the purchased they completed in that week.
So the output I would like to show on my page is similar to this :
Top buyers of the week :
1. User_1 | 150 Points
2. User_2 | 130 Points
...
10. User_10 | 10 Points
Is it possible to use annotate for that ? or it should be break ot several queries ?
Well let's give it a go (still needs to be tested for optimized SQL):
from datetime import timedelta
from django.db.models import Sum
from django.contrib.auth.models import User
from django.utils import timezone
some_day_last_week = timezone.now().date() - timedelta(days=7)
rows = User.objects.filter(purchases__date__gte=some_day_last_week)\
.annotate(item_sum=Sum('purchases__item__price'))\
.order_by('item_sum')[:10]
print [(u.username, u.item_sum) for u in rows]
I have a model similar to this one:
class Trip(models.Model):
departure = models.DateTimeField()
arrival = models.DateTimeField()
And I want to make a query that returns objects where the arrival is at least 2 hours later than the departure.
Trip.objects.filter(arrival__gt = "departure" + timedelta(hours=2))
Is this even possible? thanks
You are looking for filters that reference fields ont the model
But what if you want to compare the value of a model field with
another field on the same model?
See this sample:
>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
For your case:
from django.db.models import F
Trip.objects.filter(arrival__gt = F('departure') + timedelta(hours=2))