Get max and min formatted date values from queryset in Django - django

I have a one to many relation between session and camp. Now I have to get the max and min dates of all camps combined for a particular session.
I am able to do it like this:
sess = Session.objects.last()
max_min_dates = sess.camp.aggregate(Min('start_date'), Max('end_date'))
But if I try to send this from HttpResponse then I am getting this error:
TypeError: Object of type 'date' is not JSON serializable
So I need to send the formatted date values in that. How can I modify the above code to get the same?

The default encoder for json.dumps() does not support date encoding (ie. can't convert date into str). You can use django encoder instead, it supports a few more data types see the link for more info.
Django Ref
import json
from django.core.serializers.json import DjangoJSONEncoder
json_str = json.dumps(max_min_dates, cls=DjangoJSONEncoder)

Related

Convert a timestamp to a DateTime field?

I've got a DateTimeField(auto_now_add=True) in my model. However, I wish to update this field, and the format I'm receiving from my API is a UNIX timestamp. Can I somehow convert the format I receive from my API to the correct one? (eg 1640206232 to 2021-12-22 20:50:32).
Using postgres as my db if that matters..
Yes As mentioned by #Sevy in his comment you can use the following
from datetime import datetime
timestamp = 1640206232
dt_object = datetime.fromtimestamp(timestamp, tz='UTC') # Or whatever timezone you want
print("dt_object =", dt_object)
print("type(dt_object) =", type(dt_object))
More info and how to convert the other way can be found here:
https://www.programiz.com/python-programming/datetime/timestamp-datetime

Django JSONField - get source text

When using a JSONField, the contents are automatically decoded from JSON into python objects when reading the value. I have a use-case where I'm encoding the string back into JSON to embed in a template. Is there any way to just get the raw JSON string from the object?
Django uses psycopg2.extras.Json under the hood. You will need to cast the field as text to get the original out as plain text [1]. Use django's Cast function [2] to annotate your queryset:
from django.db.models.functions import Cast
from django.db.models import TextField
models_with_json_text = Model.objects.annotate(
json_as_text=Cast("json_field_name", TextField())
)
[1] http://initd.org/psycopg/docs/extras.html#json-adaptation
[2] https://docs.djangoproject.com/en/2.2/ref/models/database-functions/#cast

Handling Bad Inbound ISO8601 DateTime Offset with Django Rest Framework

My mobile client is sending up inaccurate datetime offset information. For example:
2019-05-03T17:55:12-0700
The time is actually the correct UTC time however, the offset should read -0000.
I can not currently modify the client to correct the issue causing this. So I need to throw out the offset or change it to -0000.
In the above example, for this user who has their account timezone settings set to PST, it stores the date in validated_data as datetime.datetime(2019, 5, 4, 0, 55, 12, tzinfo=<UTC>)
If client-based time and offset information were synced up, this conversion by DRF would be correct, as it is seven hours off or PST + the current DST. (west coast us is currently -7:00 UTC)
The problem is that by the time I reach my ModelSerializer class, the validated_data already contains what DRF believes is now the correct UTC time.
Where is the appropriate place to mutate this field on the POST body so that by the time DRF attempts to create the DateTime it will build the correct timestamp?
The easiest way to handle this was to modify the DateTime object before it was saved in the model field. So in the create() get the original ISO8601 string from the POST body using self.context['request'].data['created']. Then use dateutil.parser to parse the string into a DateTime, and replace the timezone with a pytz.UTC.
import dateutil.parser
Class MySerializer(serializers.ModelSerializer):
...
def create(self, validated_data):
scan.created = dateutil.parser.parse(self.context['request'].data['created']).replace(tzinfo=pytz.UTC)
It is not a glorious fix, but will work until I can release an updated mobile client.

Get value in a post request, Django

am getting the following post data in my django app
POST
Variable Value
csrfmiddlewaretoken u'LHM3nkrrrrrrrrrrrrrrrrrrrrrrrrrdd'
id u'{"docs":[],"dr":1, "id":4, "name":"Group", "proj":"/al/p1/proj/2/", "resource":"/al/p1/dgroup/4/","route":"group", "parent":null'
am trying to get the id value in variable id i.e "id":4 (the value 4). When I do request.POST.get('id')I get the whole json string. u'{"docs":[],"dr":1, "id":4, "name":"Group", "proj":"/al/p1/proj/2/", "resource":"/al/p1/dgroup/4/","route":"group", "parent":null' How can I get the "id" in the string?
The data you are sending is simply a json string.
You have to parse that string before you can access data within it. For this you can use Python's json module (it should be available if you're using Python 2.7).
import json
data = json.loads( request.POST.get('id') )
id = data["id"]
If you somehow don't have the json module, you can get the simplejson module.
For more details, refer this question : best way to deal with JSON in django
That's happening because id is string, not dict as it should be. Please provide your template and view code to find source of problem.

Time range query in Mongo db

I'm using django-nonrel and mongodb to develop app. I know that object id is start with a timestamp of the insertion time of object creation. So it's possible to do time range query based on _id field.
How can I generate a minimal object_id based on a given time in python or django?
Here is a much more pythonic version of the other answer here provided by OP, along with documentation:
from bson.objectid import ObjectId
import datetime
def datetime_to_objectid(dt):
# ObjectId is a 12-byte BSON type, constructed using:
# a 4-byte value representing the seconds since the Unix epoch,
# a 3-byte machine identifier,
# a 2-byte process id, and
# a 3-byte counter, starting with a random value.
timestamp = int((dt - datetime.datetime(1970,1,1)).total_seconds())
time_bytes = format(timestamp, 'x') #4 bytes
return ObjectId(time_bytes+'00'*8) #+8 bytes
However, starting with version 1.6 of pymongo, it would be much more elegant to do the following:
from bson.objectid import ObjectId
ObjectId.from_datetime(dt)
from bson.objectid import ObjectId
import time
def get_minimal_object_id_for_int_timestamp(int_timestamp=None):
if not int_timestamp:
int_timestamp=int(time.time())
return ObjectId(hex(int(int_timestamp))[2:]+'0000000000000000')
def get_int_timestamp_from_time_string(time_string=None):
# format "YYYY-MM-DD hh:mm:ss" like '2012-01-05 13:01:51'
if not time_string:
return int(time.time())
return int(time.mktime(time.strptime(time_string, '%Y-%m-%d %H:%M:%S')))
def get_minimal_object_id_for_time_string(time_string=None):
return get_minimal_object_id_for_int_timestamp(get_int_timestamp_from_time_string(time_string=time_string))
I find the solution finally. hope it helps to others.