Django DateTimeField with optional time part - django

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" }}

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

Django-Postgres: how to group by DATE a datetime field with timezone enabled

I am having this problem with prostgresql and django:
I have a lot of events that were created on a certain date at a certain time which is stored in a datetime field created .
I want to have aggregations based on the date part of the created field. The simplest examples is: how many event are in each day of this month?.
The created field is timezone aware. So the result should change depending on the timezone the user is in. For example if you created 2 events at 23:30 UTC time on 2017-10-02 if you view them from UTC-1 you should see them on 3rd of October at 00:30 and the totals should add for the 3rd.
I am struggling to find a solution to this problem that works with a lot of data. So doing for each day and SQL statement is not an option. I want something that translates into:
SELECT count(*) from table GROUP BY date
Now I found a solution for the first part of the problem:
from django.db import connection
truncate_date = connection.ops.date_trunc_sql('day', 'created')
queryset = queryset.extra({'day': truncate_date})
total_list = list(queryset.values('day').annotate(amount=Count('id')).order_by('day'))
Is there a way to add to this the timezone that should be used by the date_trunc_sql function to calculate the day? Or some other function before date_trunc_sql and then chain that one.
Thanks!
You're probably looking for this: timezone aware date_trunc function
However bear in mind this might conflict with how your django is configured. https://docs.djangoproject.com/en/1.11/topics/i18n/timezones/
Django 2.2+ supports the TruncDate database function with timezones
You can now do the following to :
import pytz
east_coast = pytz.timezone('America/New_York')
queryset.annotate(created_date=TruncDay("created", tzinfo=east_coast))
.values("created_date")
.order_by("created_date")
.annotate(count=Count("created_date"))
.order_by("-created_date")

Order by Datefield only in 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'],
)

How do I calculate the time difference in a Django template

I have a model with two TimeFields. I want to show the time difference in a template (ie, 27 minutes). I see the filter timesince, but it isn't working; I think it only accepts datetimes but my models have stored times only.
Response to #HAL:
'datetime.time' object has no attribute 'year'
Exception Location: C:\Python27\lib\site-packages\django\utils\timesince.py in timesince, line 32
You can use timesince template tag.
You can only compare two time stamps if you know their corresponding dates and timezones.. The datetime.time class contains only the time. I strongly advise you to consider using a DateTimeField (which uses datetime.datetime) in this case.
If you are sure that both datetime.time objects are having the same date and timezone, then you can add method to your model like this:
import datetime
from django.utils.timesince import timesince
class MyModel(models.Model):
...
def get_time_diff(self):
dummydate = datetime.date(2000,1,1) # Needed to convert time to a datetime object
dt1 = datetime.combine(dummydate,self.t1)
dt2 = datetime.combine(dummydate,self.t2)
return timesince(dt1, dt2) # Assuming dt2 is the more recent time
Here the time values are upgraded to a datetime value using an arbitrary date. You can invoke this from the template as {{ obj.get_time_diff }}.

Django + PostgreSQL group by date on datetimefield

I have a model which has a datetimefield that I'm trying to annotate on grouping by date.
Eg:
order_totals = Transfer.objects.filter(created__range=[datetime.datetime.combine(datetime.date.today(), datetime.time.min) + datetime.timedelta(days=-5), datetime.datetime.combine(datetime.date.today(), datetime.time.max)]).values('created').annotate(Count('id'))
The problem with the above is it groups by every second/millisecond of the datetime field rather then just the date.
How would I do this?
You should be able to solve this by using QuerySet.extra and add a column to the query
eg.
qs.filter(...).extra(select={'created_date': 'created::date'}).values('created_date')
Starting on Django 1.8, you can also use the new DateTime expression (weirdly it's is not documented in the built-in expressions sheet).
import pytz
from django.db.models.expressions import DateTime
qs.annotate(created_date=DateTime('created', 'day', pytz.UTC))
If you want to group by created_date, just chain another aggregating expression :
qs.annotate(created_date=DateTime('created', 'day', pytz.UTC)).values('created_date').annotate(number=Count('id'))
(Redundant values is needed to generate the appropriate GROUP BY. See aggregation topic in Django documentation).