In Django: I have a date and time that I need to enter into my database model, which has a column models.DateTimeField(). It seems that no matter what I do, I get a ValidationError: enter a valid date/time format.
I have a string like this:
myStr = "2011-10-01 15:26"
I want to do:
p = mytable(myDate = WHAT_GOES_HERE)
p.save()
Please don't point me to a duplicate question. I have looked around and they point to other questions which again point to questions, which point to some documentaton, which just doesn't get me what I need. Thanks!
>>> import datetime
>>> myStr = "2011-10-01 15:26"
>>> WHAT_GOES_HERE = datetime.datetime.strptime(myStr, "%Y-%m-%d %H:%M")
>>> WHAT_GOES_HERE
datetime.datetime(2011, 10, 1, 15, 26)
>>>
datetime.strptime()
From the Django documentation:
# inserting datetime.now()
import django.utils.timezone as tz
mytable.objects.create(myDate=tz.localtime())
# inserting any date:
import pytz
import django.utils.timezone as tz
from datetime import datetime as dt
my_tz = pytz.timezone('Europe/Bucharest')
my_date = dt(2018, 8, 20, 0)
mytable.objects.create(myDate=tz.make_aware(my_date, my_tz))
You can simply do the following
myStr = '2011/10/01 15:26'
And then when creating your object just use myStr as an attribute value:
p = mytable(myDate = myStr)
p.save()
Related
I have a simple serializer with a date field (not ModelSerializer).
class MySerializer(Serializer):
some_date = DateField()
I'm trying to access the date object after deserialization.
slz = MySerializer(data={"some_date": "2020-05-03"})
# I surely have a better error handling in my actual code
assert slz.is_valid()
some_extracted_date = slz.data["some_date"]
I would like my variable some_extracted_date to be a datetime.date instance.
But the value in the MySerializer.data dict is a string.
Is there a way to get this datetime.date instance ?
You access data after validation using validated_data.
>>> from app.models import MySerializer
>>> slz = MySerializer(data={"some_date": "2020-05-03"})
>>> slz.is_valid(True)
True
>>> slz.data
{'some_date': '2020-05-03'}
>>> slz.validated_data
OrderedDict([('some_date', datetime.date(2020, 5, 3))])
>>> slz.validated_data['some_date']
datetime.date(2020, 5, 3)
I am running a django where i have some sort of conditions written based on the date.
My views.py file
from django.utils import timezone
def my_method(current_date=timezone.localdate()):
logger.info(f"Current date is obtained as {current_date}")
Whenever i load the page, my views.py internally calls this method and the date doesn't gets updated daily.
In settings.py
TIME_ZONE = 'PST8PDT'
USE_TZ = True
Irrespective of today's date, it always prints old dates and after few days the date gets updated to correct date and the same date gets continued for next 4-5 days.
What is that i am doing wrong here ?
P.S. I have also tried using python's native datetime.date.today() which resulted in same abnormal behavior.
As #Willem Van Onsem mentioned in this comment,
Because you pass a datetime object as default. Note that timezone.localdate is not re-evaluated in each call. It is evaluated once, and then reused.
So, just change your function as,
from django.utils import timezone
def my_method(current_date=None):
if current_date is None:
current_date = timezone.localdate()
print(current_date)
Example
In [1]: # suppose we have a function like this,
In [2]: from datetime import datetime
...:
...:
...: def foo(default=datetime.utcnow()):
...: return default
...:
In [3]: # and I am calling this 'foo' again and again and again
In [4]: # and expecting to return different value each time
In [5]: foo()
Out[5]: datetime.datetime(2020, 7, 27, 1, 48, 30, 525369)
In [6]: foo()
Out[6]: datetime.datetime(2020, 7, 27, 1, 48, 30, 525369)
In [8]: # see there is no evaluation happening.
In [9]: #
In [10]: # So, I have changed the function to ,
In [11]: def foo(default=None):
...: if default is None:
...: default = datetime.utcnow()
...: return default
...:
In [12]: foo()
Out[12]: datetime.datetime(2020, 7, 27, 1, 50, 50, 582885)
In [13]: foo()
Out[13]: datetime.datetime(2020, 7, 27, 1, 50, 56, 356420)
For the date, you can try datetime.date.today() or datetime.datetime.now().date as long as you have the timezone configured in your settings file. You can import like from datetime import datetime.
However, I still think it's easier if you give the model a datetimefield if you have a model.
to be brief, i have this queryset:
monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total=Sum('price'))
.order_by('month'))
this is what it is returning:
[{'month': 11, 'total': Decimal('4550.00')}]
the result is going to a js script to show a graph, and i need to remove the Decimal() prefix.
Any help or hint is appreciated.
If you just want to remove "Decimal" prefix you could just define a specific output field in your annotation:
monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total=Sum('price', output_field=FloatField()))
.order_by('month'))
Since you're using Django you can use DjangoJSONEncoder as follows:
from django.core.serializers.json import DjangoJSONEncoder
my_dict = [{'month': 11, 'total': Decimal('4550.00')}]
json_result = json.dumps(my_dict, cls=DjangoJSONEncoder)
But, keep in mind that DjangoJSONEncoder turns decimal into strings so the result would be:
[{"month": 11, "total": "4550.00"}]
If you navigate to DjangoJSONEncoder source code you find this:
elif isinstance(o, (decimal.Decimal, uuid.UUID, Promise)):
return str(o)
you could convert it to a type float, like this
monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total=float(Sum('price')))
.order_by('month'))
I finally found two solutions that worked for me:
Thanks to #Ramy's answer, I overidden the DjangoJSONEncoder, to support the conversion of a Decimal to a float:
import decimal
import uuid
from django.utils.functional import Promise
from django.core.serializers.json import DjangoJSONEncoder
class JsonDecimalToFloatEncoder(DjangoJSONEncoder):
def default(self, o):
if isinstance(o, (decimal.Decimal, uuid.UUID, Promise)):
return float(o)
return super().default(o)
and I used it as he mentioned:
monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total=Sum('price'))
.order_by('month'))
json_result = json.dumps(monthly_revenue,cls=ExtendedEncoder)
json_result
'[{"month": 11, "total": 4550.0}]'
this solution requires more work on the server side, so i opted for the second solution of #rossi which does more work on the database rather than the server, and that's what the django's documentation suggest.
from django.db.models import FloatField
from django.db.models.functions import Cast
list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total_as_f=Cast('total',
output_field=FloatField()))
.order_by('month'))
[{'month': 11, 'total': Decimal('4550.00'), 'total_as_f': 4550.0}]
hope this will help anyone in the futur.
I am experiencing a strange behaviour in my views.py file:
in my user model i have
date_something = models.DateTimeField(blank=True, null=True)
The below is the code related in views.py
match = User.objects.get(email='test#test.com')
time_now = datetime.datetime.now(tz=pytz.timezone("UTC"))
match.date_something = time_now,
match.date_something2 = time_now,
# just want to check whats is stored from above line
check = match.date_something
locals()['check']
output: in the runserver console
(datetime.datetime(2019, 10, 10, 8, 20, 10, 787399, tzinfo=<UTC>),)
So here we see that the check is a tuple.
Because of this when i am trying to save the model
match.save()
it says TypeError: expected string or bytes-like object
I checked this code in dango Shell_plus and it gives the right results.
In [2]: import datetime
...: import pytz
...:
...: match = User.objects.get(email='test#test.com')
...: match.date_something = datetime.datetime.now(tz=pytz.timezone("UTC"))
...: check = match.date_something
...:
...: locals()['check']
Out[2]: datetime.datetime(2019, 10, 10, 8, 25, 59, 533597, tzinfo=<UTC>)
FOUND THE PROBLEM
I was adding a comma at the end of that line in the views.py that's why it saving as a tuple.
match.date_something = time_now,
Goal:I need to find the difference between the start_time and current_time and see if its greater then an hour .
start_time = 2016-08-15 23:52:51
current_time = 2016-08-17 13:42:12
How do that in python ?
Thanks
You have to use Datetime and timedelta
>>> from datetime import datetime
>>> delta = datetime(2016,8,15,23,52,51) - datetime(2016,8,17,13,42,12)
>>> delta
datetime.timedelta(-2, 36639)
>>> delta.seconds
36639