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
Related
how can I process a form with a field:
order = ModelChoiceField(
required=False,
queryset=OrderOd.objects.filter(Q(status='DN') | Q(status='DI')),
widget=Select(
attrs={
"class": "form-select form-select-md form-select-solid",
"data-control": "select2",
"data-multiple": "true",
"multiple": "multiple",
"data-placeholder": _("Vyberte objednávku ..."),
"id": 'order'
}
)
)
In front-end, I can select multiple orders (looks like pills/tags) and in the request sent to the server it looks like this:
movement: f2b7c234-fbdb-4059-bcb6-8ada46cef72c
account: dbabefb7-f053-4edf-a2e3-787bf6bfc371
date: 2022-09-12
order: eb2fc726-3e97-4af2-a8b2-08f20771cfef
order: 8398925b-fca6-4b25-8c48-e12940a5b5c3
order: bfa35391-5cf8-4ed8-8c44-a797da875cb4
order: 07be93ac-20b3-459c-8038-c8b023db6d66
When I inspect self.data, I got
'order': ['eb2fc726-3e97-4af2-a8b2-08f20771cfef', '8398925b-fca6-4b25-8c48-e12940a5b5c3', 'bfa35391-5cf8-4ed8-8c44-a797da875cb4', '07be93ac-20b3-459c-8038-c8b023db6d66'],
but when I check the output of logger.info(self.data['order']), it gives me only the first UUID.
[INFO] form.py 123: 07be93ac-20b3-459c-8038-c8b023db6d66
What I need is to access all UUIDs in the array (order) and process them instance by instance.
Any idea, how to do it?
Thanks
You can use self.data.getlist('order') to return the data in the array form.
see more info in Django documentation
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).
I am stuck with a silly problem.
I have a json data and trying to save it in my model.
Here is the code.
response = response.json() #this gives json data
response = json.loads(response) #loads string to json
json_string = response #ready to get data from list
modelfielda = json_string.get("abc") # this works fine
modelfieldb = json_string.get('["c"]["d"]["e"]') #this does not give data though data is present.
My json data comes like this:
{
"abc":"AP003",
"c":[
{
"d":{
"e":"some data",
"f":"some data"
}
}
]
}
So my question is how to get data inside c.
Try this for e:bnm = json_string.get('c').get('d').get('e') or with list:
bnm = json_string.get('c')[0].get('d').get('e')
By using multiple .gets:
bnm = json_string.get('c')[0].get('d').get('e') # bnm = 'some data'
Or perhaps better (since it will error in case the key does not exists):
bnm = json_string['c'][0]['d']['e'] # bnm = 'some data'
Since you converted it to a Python dictionary, you basically work with a dictionary, and you can obtain the value corresponding to a key by using some_dict[some_key]. Since we here have a cascade of dictionaries, we thus obtain the subdictionary for which we again obtain the corresponding value. The value corresponding to c is a list, and we can obtain the first element by writing [0].
I have a table that contains values saved as a dictionary.
FIELD_NAME: extra_data
VALUE:
{"code": null, "user_id": "103713616419757182414", "access_token": "ya29.IwBloLKFALsddhsAAADlliOoDeE-PD_--yz1i_BZvujw8ixGPh4zH-teMNgkIA", "expires": 3599}
I need to retrieve the user_id value from the field "extra_data" only not the dictionnary like below.
event_list = Event.objects.filter(season_id=season_id, event_status_id=2).value('extra_data')
If you are storing a dictionary as text in the code you can easily convert it to a python dictionary using eval - although I don't know why you'd want to as it opens you to all sorts of potential malicious code injections.
event_list = eval(Event.objects.filter(season_id=season_id, event_status_id=2).value('extra_data'))
user_id = event_list['user_id']
print user_id
Would give:
"103713616419757182414"
Edit:
On deeper inspection , thats not a Python dictionary, you could import a JSON library to import this, or declare what null is like so:
null = None
event_list = eval(Event.objects.filter(season_id=season_id, event_status_id=2).value('extra_data'))
user_id = event_list['user_id']
Either way, the idea of storing any structured data in a django textfield is fraught with danger that will come back to bite you. The best solution is to rethink your data structures.
This method worked for me. However, this works with a json compliant string
import json
json_obj = json.loads(event_list)
dict1 = dict(json_obj)
print dict1['user_id']
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.