Django usage of DATETIME in SQL table django_admin_log - django

Why doesn't Django in SQL table django_admin_log use TIMESTAMP instead of DATETIME for attribute action_time? I mean according to this answer it should be using TIMESTAMP.

LogEntry's action_time field is a models.DateTimeField, which (perhaps unsurprisingly) is stored as a DATETIME field.
I think you've misunderstood the answer you linked - it recommends using DATETIME, not TIMESTAMP:
If you meant that you want to decide between using a UNIX timestamp or a native MySQL datetime field, go with the native format. You can do calculations within MySQL that way ("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)") and it is simple to change the format of the value to a UNIX timestamp ("SELECT UNIX_TIMESTAMP(my_datetime)") when you query the record if you want to operate on it with PHP.

Related

django queryset with __date returns Nones

I have a django queryset where I want to group by created_at date value (created_at is a datetime field).
(Activity.objects
.values('created_at__date')
.annotate(count=Count('id'))
.values('created_at__date', 'count')
)
I am following the accepted answer here which makes sense. However, the query returns None for all created_at__date values. When I change it to created_at it shows the actual value.
The generated SQL query:
SELECT
django_datetime_cast_date("activity"."created_at", 'UTC', 'UTC'),
COUNT("activity"."id") AS "count"
FROM
"activity"
GROUP BY
django_datetime_cast_date("activity"."created_at", 'UTC', 'UTC')
I am working with local sqlite3 database, some sample records from DB (the other columns in the table are removed):
2,2021-07-30T11:44:09.984439+00:00
3,2021-07-30T11:44:29.217916+00:00
4,2021-07-30T11:44:43.598702+00:00
5,2021-08-03T20:53:48.482419+00:00
6,2021-08-04T22:19:52.810907+00:00
7,2021-08-05T17:25:29.646553+00:00
8,2021-08-05T17:25:33.425523+00:00
9,2021-08-05T17:26:22.169369+00:00
10,2021-08-05T17:50:26.585485+00:00
11,2021-08-10T16:20:38.839126+00:00
12,2021-08-10T17:38:00.557487+00:00
13,2021-08-11T16:09:30.470890+00:00
14,2021-08-11T16:09:34.164904+00:00
15,2021-08-12T15:43:18.819458+00:00
16,2021-08-12T16:19:30.123575+00:00
18,2021-08-15T12:55:20.660137+00:00
24,2021-08-18T18:21:12.153480+00:00
25,2021-08-18T19:18:37.432911+00:00
The reason is sqlite3 database can not store timezone information as it does not support built-in date and/or time. And since the sample date contains timezone information, sqlite3 is unable to extract date from the datetime field, and showing None.
correct format for sqlite3
2021-11-29 12:40:20.021350

Django ORM converting date to datetime which is slowing down query 30x

I'm attempting query a table and filter the results by date on a datetime field:
.filter(bucket__gte = start_date) where bucket is a datetimefield and start_date is a date object.
However django converts the start_date to a timestamp in the raw sql ex 2020-02-01 00:00:00 when I want it just be a date ex 2020-02-01.
For some reason casting bucket to a date or casting start_time to a timestamp makes the query 30x slower.
When I manually write a query and compare bucket directly to a date ex bucket >= '2020-02-01' the query is blazing fast.
How can I get the django orm to do this?
Seems that its most efficient to convert your date to a datetime in python then do the lookup on the orm since you are filtering on a DateTimeField
from datetime import datetime
.filter(bucket__gte=datetime.combine(start_date, datetime.min.time()))
If the field bucket is indexed, the explain of this query should indicate an Index Scan which would provide desired and most efficient execution plan.
If not it should still be faster since you avoid casting
For some reason casting bucket to a date or casting start_time to a timestamp makes the query 30x slower.
Yes, casting bucket to a date would prevent use of an index (unless the index was over the casted column). But casting start_time to a timestamp would not. What is it 30 times slower than? You just said python automatically converts it, so, how is that different than casting it? As in, what is your actual code?
When I manually write a query and compare bucket directly to a date ex bucket >= '2020-02-01' the query is blazing fast.
OK, but what is it actually doing?
explain select * from foo where bucket > '2021-03-01';
QUERY PLAN
-------------------------------------------------------------------------
Seq Scan on foo (cost=0.00..38.25 rows=753 width=8)
Filter: (bucket > '2021-03-01 00:00:00-05'::timestamp with time zone)
(2 rows)
PostgreSQL is also converting it to a timestamp. Does it give the right answer or the wrong answer?
Try convet your datetime to date in filter:
.filter(bucket__date__gte = start_date)

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

Update value of a column in postgres into lower case

I have a table name service_table which have some fields. A field have days name like Sunday, Monday, Tuesday etc.. I want to change all the column value in postgres database table into lower case.
For Instance
'Sunday' update as 'sunday'
I am written a query
update service_table set days=lower(days);
but it shows
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Note: This table has some foreign key.
You can do this in Django shell
from django.db.models import F
from django.db.models.functions import Lower
service_table.objects.update(days=Lower(F('days'))
Django update() is a bulk operation for direct updates.
Django F() makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.
F() helps to pull the model field value, then it process to the requirement and use update() to save it back

how to extract date from a datetime field inside a filter in django

I have used this query in my view..
temp2=transaction.objects.filter(user_id=client_obj,Date_of_trans.date()=rec_var1)[0].Trans_Amount
I need to compare a datetime field present in my model named Date_of_trans to a variable received from user but the code is not working... what query should be written?
This is basically a sql query. So you should think like that. How can you do this in sql. I mean what condition will you apply in sql. For finding records of particular date with datetime field you should check records between start of the day to end of the day.
try this
from datetime import datetime, time
temp2=transaction.objects.filter(user_id=client_obj,Date_of_trans>datetime.combine(rec_var1, time(0,0,0)), Date_of_trans <= datetime.combine(rec_var1, time(23,59,59)) )[0].Trans_Amount
The above code is written taking into consideration that rec_var1 is a date() object.
Here you check all transactions between start of the day, till end of the day. I think this will resolve your problem.
I've use datetime.combine function which combines date and time object to form datetime object which is required here.
Thanks