Order by Datefield only in Django - django

I want to sort by DateTimeField ignoring one hour.
Because in my ordination I need
Person.objects.order_by('-date_joined', 'full_name')
Sorting by name has no effect because it is a Timefield , but I wanted to data.

Depending on your Django version (1.9+), this should work:
Person.objects.order_by ('-date_joined__date','full_name')
Otherwise you can use .extra to cast into date field:
Person.objects.extra(
select={'joined_date': 'DATE(myapp_person.date_joined)'},
order_by=['-joined_date', 'full_name'],
)

Related

Order by time of a Datetime field in django

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')

Group objects by dates

clicks = SellerClick.objects.extra({'date' : "date(timestamp)"}).values('date').annotate(count=Count('timestamp'))
The model has a datetime field called timestamp that was are using. I first, convert the datetime field to just a date field. Then the rest is guessing. I need to group by, and then count how many objects are of each date.
So the desired result would be a date, then a count, based on how many objects have that date in the timestamp field.
I prefer to use annotate over extra
from django.db.models.expressions import RawSQL
SellerClick.objects.annotate(
date=RawSQL('date(date_joined)',[]),
).values('date').annotate(count=Count('date')))
You've got everything but an initial queryset there. The extra sql you're passing doesn't include a select so you need to give it something to act on.
clicks = SellerClick.objects.all()
.extra({'date' : "date(timestamp)"})
.values('date')
.annotate(count=Count('timestamp'))
Ref: StackOverflow: Count number of records by date in Django

Django: DateTimeField, how to make require only date.

I want to have DateTimeField(Not separate DateField and TimeField) but i want only date to be required or only time to have default value. Is it possible and if yes .. how :)

Django DateTimeField with optional time part

I have a field which will represent the start time of an event and I am using the Django DateTimeField for this.
This field is mandatory but sometimes the users will only know the start date and not the time.
Is there anyway to make the time part optional and keep the date part mandatory?
Maybe you should try to separate date from time. There are DateField and TimeField for that.
Example for use at the views or models:
You can use function strptime to show the datetime field any formats.
from datetime import datetime
datetime.now().strftime('%Y-%m-%d')
# print string '2013-06-25'
Example for use at the templates:
you can use templatetag date
{{ datetime_field|date:"Y-m-d" }}

Django: order by position ignoring NULL

I have a problem with Django queryset ordering.
My model contains a field named position, a PositiveSmallIntegerField which I'd like to used to order query results.
I use order_by('position'), which works great.
Problem : my position field is nullable (null=True, blank=True), because I don't wan't to specify a position for every 50000 instances of my model. When some instances have a NULL position, order_by returns them in the top of the list: I'd like them to be at the end.
In raw SQL, I used to write things like:
IF(position IS NULL or position='', 1, 0)
(see http://www.shawnolson.net/a/730/mysql-sort-order-with-null.html). Is it possible to get the same result using Django, without writing raw SQL?
You can use the annotate() from django agrregation to do the trick:
items = Item.objects.all().annotate(null_position=Count('position')).order_by('-null_position', 'position')
As of Django 1.8 you can use Coalesce() to convert NULL to 0.
Sample:
import datetime
from django.db.models.functions import Coalesce, Value
from app import models
# Coalesce works by taking the first non-null value. So we give it
# a date far before any non-null values of last_active. Then it will
# naturally sort behind instances of Box with a non-null last_active value.
the_past = datetime.datetime.now() - datetime.timedelta(days=10*365)
boxes = models.Box.objects.all().annotate(
new_last_active=Coalesce(
'last_active', Value(the_past)
)
).order_by('-new_last_active')
It's a shame there are a lot of questions like this on SO that are not marked as duplicate. See (for example) this answer for the native solution for Django 1.11 and newer. Here is a short excerpt:
Added the nulls_first and nulls_last parameters to Expression.asc() and desc() to control the ordering of null values.
Example usage (from comment to that answer):
from django.db.models import F
MyModel.objects.all().order_by(F('price').desc(nulls_last=True))
Credit goes to the original answer author and commenter.
Using extra() as Ignacio said optimizes a lot the end query. In my aplication I've saved more than 500ms (that's a lot for a query) in database processing using extra() instead of annotate()
Here is how it would look like in your case:
items = Item.objects.all().extra(
'select': {
'null_position': 'CASE WHEN {tablename}.position IS NULL THEN 0 ELSE 1 END'
}
).order_by('-null_position', 'position')
{tablename} should be something like {Item's app}_item following django's default tables name.
I found that the syntax in Pablo's answer needed to be updated to the following on my 1.7.1 install:
items = Item.objects.all().extra(select={'null_position': 'CASE WHEN {name of Item's table}.position IS NULL THEN 0 ELSE 1 END'}).order_by('-null_position', 'position')
QuerySet.extra() can be used to inject expressions into the query and order by them.