Django - Serializing model with additional data - django

I am trying to serialize some model data along with some extra information like so:
data = {
'model_data': serializers.serialize('json', SomeModel._default_manager.all(), fields=('name','last_updated')),
'urls': {
'updateURL':'http://www.bbc.co.uk',
},
}
json = simplejson.dumps(data)
It seams my 'model_data' object is being serialized twice as it seems to be returned as a string and not a valid json object:
Object
model_data: "[{"pk": 1, "model": "models.SomeModel", "fields": {"last_updated": null, "name": "Name test"}}]"
urls: Object
What am I doing wrong here?

How about having the value of the model_data field be handled again by another JSON processor? I think it will be the same, since the JSON processor always expects a string that is always in the correct format.

Related

Deserializing datetime double encodes date

I am trying to deserialize a datetime value:
def default(o):
if type(o) is datetime.date or type(o) is datetime.datetime:
return o.isoformat()
def get_user_join_date(user):
return json.dumps(
user.date_joined,
sort_keys=True,
indent=1,
default=default
)
in order to use it as a value in payload:
def jwt_payload_handler(user, active_site):
payload = {
"id": user.id,
"date": get_user_join_date(user),
"username": user.username,
"role": user.role
}
The problem is that my datetime ends up being double encoded (it has 2 double quotes)
date: ""2018-09-27T12:32:17.577000+00:00""
Any idea why this might be happening and how I can solve it?
What's happening here is that the date string is encoded twice.
The return value of get_user_join_date(user) is the string '"2018-09-27T12:32:17.577000+00:00"' (so the ISO formatted datetime surrounded by double quotes).
This string is put into the payload and is again dumped to JSON by whatever you're using to create the JWT token.
A reduced example of what you are seeing would be this:
import json
import datetime
def default(o):
if type(o) is datetime.date or type(o) is datetime.datetime:
return o.isoformat()
print(json.dumps({
'date': json.dumps(
datetime.datetime.now(),
default=default
)
}))
Which produces the output you are seeing:
{"date": "\"2018-10-09T12:53:04.914694\""}
There are a few solutions to this issue:
The easiest solution to this issue would be to not use json.dumps in get_user_join_date and simply return user.date_joined.isoformat() instead.
Another solution would be to return user.date_joined from get_user_join_date and somehow pass the custom default function to the JSON encoder used by whatever is processing that JWT payload.
It might also be possible to just return the date object from get_user_join_date, but only if the library you're using is smart enough to handle datetime objects (some are).

Fetch Json Field value using Values in Django

I have a JSON field in my model and by using values option, I would like to get the key value present in the JSON field.
Assume my JSON field value is:
{"key1":"value1","key2":"value2"}
MyClass.objects.values("field1","field2","JSON Key")
Let JSON Key be "Key1"
Expected O/P:
[{field1:Value1,field2:value2,Key1:value1}]
A better solution (for Django >= 1.11) would be to use KeyTextTransform, like so:
from django.contrib.postgres.fields.jsonb import KeyTextTransform
MyModel.objects\
.annotate(key1=KeyTextTransform('key1', 'myjsonfield'))\
.values('field1','field2','key1')
I have written a custom manager function in ActiveQuerySet which accepts a list of fields and give get the particular field information from the object.
I have written the script for simple json structure..but where as u can change the way of processing json according to requirement.
The ActiveQuerySet class is as below.
class ActiveQuerySet(models.QuerySet):
def custom_values(self,*args,**kwargs):
model_fields = self.model._meta.get_fields()
model = [str(i.name) for i in model_fields]
json_fields = [str(i.name) for i in model_fields if i.get_internal_type() == 'JSONField']
responses = []
for one in self:
one_value = {}
for i in args[0]:
if i in model: # search if field is in normal model
one_value[i]=str(getattr(one,i))
else:
for jf in json_fields: #get all json fields in model
try:
json_value = eval(getattr(one,jf)) #eval to json or dict format if required
except:
json_value = getattr(one,jf)
json_keys = json_value.keys() #get the keys from json data stored
if i in json_keys:#check if key is present
one_value[i] = json_value[i]
responses.append(one_value)
return responses
MyModel.objects.all().custom_values(['field1','field2','key(which is present in JOSN field)'])
Assume my json data is stored as
{"cluster": "Mulchond", "2962": "2016-12-13", "2963": "1", "2964": "4", "2965": "0", "2966": "0", "2967": "0", "2968": "0.0318", "2969": "0.0705", "2970": "", "2971": "", "2972": "", "2973": "17.256", "2974": "48.8351", "2975": "142", "2976": "783", "2977": "276", "2978": "0.05237", "2979": "70", "2980": "0.05237", "2981": "", "2982": "", "2983": "", "2984": "142", "2985": "32", "2986": "", "2987": "20.773551", "2988": "73.649422"}
from this I want to get value of key '2988', My Query be like
MyModel.objects.filter().custom_values(['id','2988'])
o/p :
[{'2987': '20.730995', 'id': '66302'},
{'2987': '20.766556', 'id': '66303'},
{'2987': '20.773551', 'id': '66304'}]
where 'id is generated by Django and '2987' is one key which is present in JSON Field

Using knockout destroy() with django deserializer

In knockout.js there is a function called destroy() See bottom of this page
It says that it is useful for Rails developers as it adds a _destroy attribute to a object in an observerable array
Im using django and trying to use the same function to know which objects to delete from my database - and as far as i understand a django deserialized object only contains the and pk what is in the fields object
this is what the json looks like:
{"pk": 1,
"model": "eventmanager.datetimelocgroup",
"fields": {"event": 10},
"_destroy": "true"
}
As of now i have very ugly but working code - i was wondering if there is any shorter way to detect if a deserialized object had a destroy flag
my current code looks like this
ra = []
removejson = json.loads(eventslist)
for i,a in enumerate(removejson):
if '_destroy' in a:
ra.append(i)
for index,event in enumerate(serializers.deserialize("json", eventslist)):
if index in ra:
try:
e = Event.objects.get(id = event.object.pk)
e.delete()
except ObjectDoesNotExist:
pass
else:
event.save()
I was wondering if there is a better way than going through the json multiple time
This oneliner should work (please understand it before trying it out):
Event.objects.filter(
id__in = [
x['fields']['event'] for x in json.loads(eventslist) if '_destroy' in x
]
).delete()

Convert ObjectId of mongodb object to string

How to convert ObjectId of mongodb object in string format.
ObjectId('5323d54c41cf6e0ffab13384')
I have above ObjectId and i want to convert this ObjectId back to string name from which its generated. Is there any way that i can directly display name from above ObjectId in django template. Please suggest.
Just get the string representation:
ObjectId('5323cc2770fde63cf1146ba3')
>>> str(o)
'5323cc2770fde63cf1146ba3'
Also see the documentation
From your comments though you do not seem to have a full understanding of what an ObjectId is and I would suggest you do some reading on that. Also read up on documents in general.
What you seem to be asking, which is not how your question reads is how do I get the "properties" from an ObjectId you received after you saved a "document" or, otherwise in some form or another. You get the "document" by querying the database:
var doc = db.collection.findOne({ _id: ObjectId('5323cc2770fde63cf1146ba3') })
And then you can access the "properties" of the document you received. So the resulting "document" you fetch might look like this:
{
"_id": ObjectId('5323cc2770fde63cf1146ba3').
"name": "Neil",
"favouriteColour": "Blue",
"age": "Don't Ask"
}
An ObjectId by itself contains no magic information. It is a primary key, to a document that exists in the collection.

Django deep serialization - follow reverse foreign key constraints

I have two models with a foreign key relationship:
class Company(models.Model):
field 1
field 2
class Employee(models.Model):
company = Model.ForeignKey('Company')
field 3
field 4
I would like to JSON serialize a company instance, and include all employees that have foreign-key relationships to it. IE, I'd like to create JSON that looks something like the following, in that it includes all fields for a company and all fields for all related employees.
[
{
"pk": 2,
"model": "app.company",
"fields": {
"field1": "value",
"field2": "value",
"employee": [
{
"pk": 19,
"model": "app.employee",
"fields": {
"field3": "value",
"field4": "value",
}
},
{
"pk": 25,
"model": "app.employee",
"fields": {
"field3": "value",
"field4": "value",
}
}
]
}
}
]
The Django serializer doesn't serialize relationships. Other questions here have asked how to deep serialize, but in the opposite direction -- IE, serialize an employee along with its related company. Answers to these questions have pointed out that the wadofstuff django-full-serializer plugin allows you to do this kind of deep serialization. The problem is that the wadofstuff plugin only follows these relationships unidirectionally -- it won't follow a reverse foreign key constraint. So, I'm trying to roll my own here. Any suggestions on how to accomplish this?
So, here's a super budget way of doing this which works for my purposes, but I feel like there has to be a better way (including it here in case others are looking for how to do this). It works for me only because I'm sending just one Company object at a time, and as such the fact that it doesn't explicitly preserve the relationship hierarchy isn't a big deal.
Given Company instance of "company":
companyJSON = serializers.serialize('json', [company, ])
employeeJSON = serializers.serialize('json', company.employee_set.all())
fullJSON = companyJSON[:-1] + ", " + employeeJSON[1:]