I wanted to order a query set on the basis of a time of a datetime field.
I have used the following (here Tasks is my model and datetime is the field)
Tasks.objects.all().order_by('datetime.time')
this doesn't work and also
Tasks.objects.all().order_by('datetime__time')
doesn't work as it is part of the same model.
I tried using .annotate() but I don't know how exactly to do it.
How should I go about doing this?
Tasks.objects.all().order_by('datetime__hour')
or
Tasks.objects.all().order_by('datetime__minute')
Task.objects.all().order_by('datetime__hour', 'datetime__minute')
I'm trying to display the expiry date of a bonus from within a Django template. At the moment the opening_date is stored as a datefield and we store the bonus term as an integerfield. Unfortunately just trying to add the bonus term to the opening date fails and the furthest I have got so far is:
{{product_form.instance.opening_date|add:product_form.instance.bonus_term}}
I have tried just adding it to the month but unfortunately I need the whole date returned to display.
For a better idea of what I want is say the opening date was 01/01/2012 and the bonus term was 12, I want to display the expiry date of 01/01/2013. I realise this is probably better off being in the database but due to the way it has been previously set up there is a large amount of existing data that wouldn't have it.
Thanks.
I think that, for your scenario, the most elegant solution is to create a model method in your model that calcule expire date, then call the method in template:
In model:
class product(models.Model):
opening_date = ...
bonus_term = ...
def expire_date( self ):
return self.opening_date + timedelta( days = self.bonus_term )
In template:
{{product_form.instance.expire_date}}
I'm sure that you will call this method in more other lines of your code.
I have a Django model with a created timestamp and I'd like to get the counts of objects created on each day. I was hoping to use the aggregation functionality in Django but I can't figure out how to solve my problem with it. Assuming that doesn't work I can always fall back to just getting all of the dates with values_list but I'd prefer to give the work to Django or the DB. How would you do it?
Alex pointed to the right answer in the comment:
Count number of records by date in Django
Credit goes to ara818
Guidoism.objects.extra({'created':"date(created)"}).values('created').annotate(created_count=Count('id'))
from django.db.models import Count
Guidoism.objects \
# get specific dates (not hours for example) and store in "created"
.extra({'created':"date(created)"})
# get a values list of only "created" defined earlier
.values('created')
# annotate each day by Count of Guidoism objects
.annotate(created_count=Count('id'))
I learn new tricks every day reading stack.. awesome!
Use the count method:
YourModel.objects.filter(published_on=datetime.date(2011, 4, 1)).count()
Is there a method that I am not finding for getting the distinct hours in a DateTimeField? I essentially want the exact same thing that .dates() provides but for hours.
I should clarify that I am talking about a QuerySet method. The dates() method I am talking about is here:
http://docs.djangoproject.com/en/1.1/ref/models/querysets/#dates-field-kind-order-asc
If not, is there a recommended known solution?
Thanks.
Adding for clarification:
I have a model called Event with a DateTimeField called start_date. We need to know which hours of a particular day have an event.
Let's say that we narrow it down to a particular month:
objects = Event.objects.filter(start_date__year=2010, start_date__month=2)
Now the dates functions could give me a a list of all the days that have an event:
distinct_days = objects.dates('start_date', 'day')
What I would like is the narrow it down to a particular day, and then get a distinct list of the hours in the day that have an event.
objects = Event.objects.filter(start_date__year=2010, start_date__month=2, start_date__day=3)
distinct_hours = objects.times('start_date', 'hour') # This command doesn't exist and am wondering how to do this
Thanks.
Do you want to get the hours from a datetime object? Which .dates() do you mean?
hour = instance.yourDateTimeField.hour
Unfortunately there isn't a good way to do this at present, the best way is to use some raw SQL in conjunction with the extra() method and then call distinct().
I have created this code in order to manually do it.
hours = []
for h in objects.values('start_date'):
hours.append(h['start_date'].hour)
tempdict = {}
for x in hours:
tempdict[x] = x
hours = tempdict.values()
hours.sort()
Simple solution: hours might be stored in separate field, with unique=True.
How can I retrieve the last record in a certain queryset?
Django Doc:
latest(field_name=None) returns the latest object in the table, by date, using the field_name provided as the date field.
This example returns the latest Entry in the table, according to the
pub_date field:
Entry.objects.latest('pub_date')
EDIT : You now have to use Entry.objects.latest('pub_date')
You could simply do something like this, using reverse():
queryset.reverse()[0]
Also, beware this warning from the Django documentation:
... note that reverse() should
generally only be called on a QuerySet
which has a defined ordering (e.g.,
when querying against a model which
defines a default ordering, or when
using order_by()). If no such ordering
is defined for a given QuerySet,
calling reverse() on it has no real
effect (the ordering was undefined
prior to calling reverse(), and will
remain undefined afterward).
The simplest way to do it is:
books.objects.all().last()
You also use this to get the first entry like so:
books.objects.all().first()
To get First object:
ModelName.objects.first()
To get last objects:
ModelName.objects.last()
You can use filter
ModelName.objects.filter(name='simple').first()
This works for me.
Django >= 1.6
Added QuerySet methods first() and last() which are convenience methods returning the first or last object matching the filters. Returns None if there are no objects matching.
When the queryset is already exhausted, you may do this to avoid another db hint -
last = queryset[len(queryset) - 1] if queryset else None
Don't use try...except....
Django doesn't throw IndexError in this case.
It throws AssertionError or ProgrammingError(when you run python with -O option)
You can use Model.objects.last() or Model.objects.first().
If no ordering is defined then the queryset is ordered based on the primary key. If you want ordering behaviour queryset then you can refer to the last two points.
If you are thinking to do this, Model.objects.all().last() to retrieve last and Model.objects.all().first() to retrieve first element in a queryset or using filters without a second thought. Then see some caveats below.
The important part to note here is that if you haven't included any ordering in your model the data can be in any order and you will have a random last or first element which was not expected.
Eg. Let's say you have a model named Model1 which has 2 columns id and item_count with 10 rows having id 1 to 10.[There's no ordering defined]
If you fetch Model.objects.all().last() like this, You can get any element from the list of 10 elements. Yes, It is random as there is no default ordering.
So what can be done?
You can define ordering based on any field or fields on your model. It has performance issues as well, Please check that also. Ref: Here
OR you can use order_by while fetching.
Like this: Model.objects.order_by('item_count').last()
If using django 1.6 and up, its much easier now as the new api been introduced -
Model.object.earliest()
It will give latest() with reverse direction.
p.s. - I know its old question, I posting as if going forward someone land on this question, they get to know this new feature and not end up using old method.
In a Django template I had to do something like this to get it to work with a reverse queryset:
thread.forumpost_set.all.last
Hope this helps someone looking around on this topic.
MyModel.objects.order_by('-id')[:1]
If you use ids with your models, this is the way to go to get the latest one from a qs.
obj = Foo.objects.latest('id')
You can try this:
MyModel.objects.order_by('-id')[:1]
The simplest way, without having to worry about the current ordering, is to convert the QuerySet to a list so that you can use Python's normal negative indexing. Like so:
list(User.objects.all())[-1]