How to get django queryset results with formatted datetime field - python

I've Django model which has foreign keys associated with other models. Each model is having same field names(attributes) created_at and updated_at
In every django queryset results I'll be getting datetime values.
Model.objects.all().values('created_at')
But I want to format the datetime field to "DD-MM-YYYY HH:MM:SS" and trim down the milliseconds in the django query results.
If I use "extra" and and date_trunc_sql like the following command
dt = connection.ops.date_trunc_sql('day','created_date')
objects.extra({'date':dt}).values('date')
Which works fine. But If I query like the following, its raising ambiguous statement error.
objects.extra({'date':dt}).values('date', 'x', 'y', 'z')
How to overcome this problem?

Solved it via #Yannics answer at: https://stackoverflow.com/a/60924664/5804947
This also avoids using extra which should be "a last resort" due to Django docs.
from django.db.models import F, Func, Value, CharField
qs.annotate(
formatted_date=Func(
F('created_at'),
Value('DD-MM-YYYY HH:MM:SS'),
function='to_char',
output_field=CharField()
)
)

Got the solution.
data = list(Model.objects.extra(select={'date':"to_char(<DATABASENAME>_<TableName>.created_at, 'YYYY-MM-DD hh:mi AM')"}).values_list('date', flat='true')
It's not just tablename.attribute, it should be dbname_tablename.attribute when we have multiple databases(ambiguous)
which will result list of created_at datetime values trimmed to 'YYYY-MM-DD HH:MM' format.

I don't think values() function would anything related to formatting datetime result. But why does that bother you? Can't you convert them to proper format when you try to display them? If you try to render them in the template, django has template filter date for formatting your datetime value: https://docs.djangoproject.com/en/1.9/ref/templates/builtins/#date

Related

Formatting DateTimeField in Django

When saving timestamp in Django's DateTimeField using auto_now_add this way:
creation_timestamp = models.DateTimeField(auto_now_add=True)
the field is saved with miliseconds:
2018-11-20T15:58:44.767594-06:00
I want to format this to be displayed without miliseconds:
2018-11-20T15:58:44-06:00
But the only option I could come up with does not exactly show what I need:
format="%Y.%m.%dT%H:%M:%S%z" gives me 2018.11.20T15:58:44-0600
How do I format this field the way I need?
Alternatively I'd rather save DateTimeField without milliseconds at all but does auto_now_add allow to do this sort of thing?
If you want to format it on when displaying it, you can use: creation_timestamp.strftime("%Y-%m-%d%H:%M:%S")
You can also make DateTimeField to save it in that format, but this would request a set of changes which will apply system wide:
In your settings file set the follwing:
DATETIME_FORMAT="%Y-%m-%d%H:%M:%S"
L10N=False to make sore localization data doesn't take precedent when it comes to dates format.
USE_TZ=False
But, consider the fact that this changes will apply by default to all date time objects from your project.
You can override DateTimeField's value_to_string method and add the changes there. For example:
class CustomDateTimeField(models.DateTimeField):
def value_to_string(self, obj):
val = self.value_from_object(obj)
if val:
val.replace(microsecond=0)
return val.isoformat()
return ''
And use it in model:
created = CustomDateTimeField(auto_now_add=True)
I think you will have to use isoformat. Look at that answer:
Show the : character in the timezone offset using datetime.strftime
I use pandas to_datetime() function to convert the time to string format.
import pandas as pd
record_list = myModel.objects.all()
for idx, record in enumerate(record_list ):
st = str(pd.to_datetime(record.start_time))
record_list[idx].start_time = st

Group By using Timestamp in Django Queryset

I have one model where each entry is stored and its created time is stored. The time is not a datetime object a timestamp. Timestamp field of model is shown below :
logged_at = models.CharField(_('log time'), max_length=128,
default=time.time)
If above field is datetime field then I can write an query which can group by records using datetime field like :
MyModel.objects.filter(type_='in').annotate(in_time=RawSQL('(date(logged_at))', [])).values('in_time', 'name').annotate(count=Count('name'))
But I am not able to query the timesatmp field in same way , It gives me the error date/time field value out of range
I have also tried to use functions like to_timestamp nut still no success
MyModel.objects.filter(type_='in').annotate(in_time=RawSQL('(date(to_timestamp(logged_at)))', [])).values('in_time', 'name').annotate(count=Count('name'))
Error : function to_timestamp(character varying) does not exist
Database I am using is Postgres
As #Willem mentioned in comment that timestamp must not be stored in CharField. So We can try to change type of field at runtime like given below.
MyModel.objects.filter(type_='in').annotate(in_time=RawSQL('(date(to_timestamp(logged_at::float)))', [])).values('in_time', 'name').annotate(count=Count('name'))
IN above query I have changed type of logged_at to float and it works fine for me, you can also change it to int.

use __gte for string date django

Date is in string format in database
class A(models.Model):
date = models.CharField(max_length=50, blank=True, null=True)
Yah i know it should be date type.
but now we have many records and we will soon change it to date type.
For current status i want get the objects greater than particular date.
So how can i use date__gte
example
objs = A.objects.filter(date__gte=datetime.now())
Is there any way to achieve this without converting date to datetime field.
I am not sure if that works. What you can try is a custom manager. So you can create a manager for your model, add something like date_gte and then convert the string to a datetime. Then you can user those operators as usual. That's a quick fix for now, but the best solution is to use a DateTimeField, which you want to do as far as I understood.
Example Manager:
from django.db import models
class MyManager(models.Manager):
def date_gte(self, date=datetime.now()):
items = []
for obj in self.all():
if datetime(obj.date) < date:
items.append(obj)
return items
Then you could call it like MyModel.objects.date_gte(date=datetime.now()).
Note: This is an expensive query and you may need to convert the simple list into QuerySet object. I haven't tested it, so this example should only help you get started.
There is no way to do this without a conversion (either in Django or the database during the query) to a proper DateTime type. You're trying to compare a datetime.datetime to a str. That won't work in normal Python and it won't work here.
What kind of string? if it is formatted to %Y%m%d, you can use .extra() method to do the query.
A.objects.extra(where=['date >= date_of_today'])

Modifying display format of DateTimes in django-tables2

I'm currently using django-tables2 to display a queryset of my model. One of the attributes of this model is a DateTimeField accurate to the millisecond which is being truncated to the minute in my table.
I had previously manually implemented a simple table in HTML and had no issues. My DateTimeFields were following true to the DATETIME_FORMAT applied in my settings:
settings.py
DATETIME_FORMAT = 'Y N j, H:i:s.u'
The problem has arisen since I began using django-tables2. Is there some way to modify the way it displays DateTimeFields or make it follow my specified DATETIME_FORMAT? I need to retain the sorting functionality so converting to a string is not an option.
I'm using render_table to display my table. The following is my table class:
class ModelTable(tables.Table):
class Meta:
model = Measurement
sequence = ('date_time', 'latitude', 'longitude',
'depth', 'soundvel', 'instrument')
Problem solved.
django-table2's DateTimeColumn class seems to be looking for a SHORT_DATETIME_FORMAT rather than the DATETIME_FORMAT in my settings.py. Updated the value in my settings file and everything is in working order.
This confused me for a while as I tried to use the Python datetime formatting options. The formatting options for Django templates apply in django-tables2, and are fully enumerated at the Django docs:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#std:templatefilter-date
From that, if you have a model with one datetime column, and you want their birthday to be formatted as Month Day Year, Hour:Minute AM/PM, then you would enter the following:
class MyTable(tables.Table):
birthday = tables.DateTimeColumn(format ='M d Y, h:i A')
class Meta:
model = Person
attrs = {'class': 'table'}
fields = ['birthday']
You can add 'format' as argument to DateTimeColumn.
https://django-tables2.readthedocs.io/en/latest/_modules/django_tables2/columns/datetimecolumn.html
class DateTimeColumn(TemplateColumn):
"""
A column that renders `datetime` instances in the local timezone.
Arguments:
format (str): format string for datetime (optional).
Note that *format* uses Django's `date` template tag syntax.
short (bool): if `format` is not specified, use Django's
``SHORT_DATETIME_FORMAT``, else ``DATETIME_FORMAT``

django's DateField model field and acceptable values

I'm having a bit of trouble with django's DateField model field. Shouldn't it be able to accept fiveDaysLater as a valid date object? When I try to add fiveDaysLater into the database, I get an error saying cannot add null value to date. However, the second I change the date field to a regular CharField, the fiveDaysLater value is added to the database with no problem. fyi if I print fiveDaysLater, I get 2011-09-28
My view:
def myView():
now = datetime.date.today()
fiveDaysLater = now + datetime.timedelta(days=5)
newDate = Speech(date = fiveDaysLater)
newDate.save()
My model
class Speech(models.Model):
date = models.DateField()
"However, the second I change the date field to a regular CharField..." Just a suspicion but if you made this change in your code, make sure to delete and recreated the Speech table using syncdb, otherwise, sqlite will not be aware of this change. (or you could change the datatype using sqlite exporer for firefox or something like that...)

Categories

Resources