Get data from JsonResponse in django - django

I wanted to know how to get data from a JsonResponse in django. I made a JsonResponse that works like this
def pfmdetail(rsid):
snpid = parseSet(rsid)
if not snpid:
return HttpResponse(status=404)
try:
data = SnpsPfm.objects.values('start', 'strand', 'type', 'scoreref', 'scorealt',
rsid=F('snpid__rsid'), pfm_name=F('pfmid__name')).filter(snpid=snpid[0])
except SnpsPfm.DoesNotExist:
return HttpResponse(status=404)
serializer = SnpsPfmSerializer(data, many=True)
return JsonResponse(serializer.data, safe=False)
and then I call directly the method like this
def pfmTable(qset,detail):
source = pfmdetail(detail)
print(source)
df = pd.read_json(source)
but it gives me an error. I know it's wrong because with the print it returns the status of the response which is 200 so I suppose that the response is fine but how can I access the data inside the response? I tried import json to do json.load but with no success. I even tried the methods of QueryDict but stil I can't acess to the content I'm interested
P.S. I know that data contains something because if i display the jsonresponse on the browser i can see the JSON

As you can see here: https://docs.djangoproject.com/en/2.2/ref/request-response/#jsonresponse-objects.
JsonResponse object holds json in its content attribute.
So to access it try this:
df = pd.read_json(source.content)
Or to see it printed do:
print(source.content)

If you aren't using pandas, then you should process the content attribute of the JSONResponse object like this:
r = json.loads(source.decode())
I got the answer here: How to parse binary string to dict ?

Related

How to encode a django query set specific field to a Json response?

I do a filter to obtain a particular set of objects from django data model. I need to encode only a single field of that objects to a json response.
e.g.: Item has an attribute called name.
qs_available = Item.objects.filter(Type=1).values.('name').???
return HttpResponse(json.dumps(qs_available), content_type='application/json')
How do I return the list of name values as a json response?
If you want to get only names list, you can use values_list
qs_available = list(Item.objects.filter(Type=1).values_list('name', flat=True))
return HttpResponse(json.dumps(qs_available), content_type='application/json')
You could use JsonResponse from django.http,
from django.http import JsonResponse
qs_available = Item.objects.filter(Type=1).values_list('name')
return JsonResponse(list(qs_available), safe=False)

How can I write tests that populates raw_post_data and request.FILES['myfile']

I have something like this:
def upload_something(request):
data = {}
if request.FILES:
raw_file = request.FILES['myfile'].read()
else:
raw_file = request.raw_post_data
I can't seem to be able to write a unit-test that populates raw_post_data, how would I go about doing that? I basically just want to send an image file. I'm trying to create a test case for when I read raw_post_data and it errors with:
You cannot access raw_post_data after reading from request's data stream
I'm assuming you have figured this out by now, but as the answers are almost out of date with the deprecation of raw_post_data I thought i'd post.
def test_xml_payload(self):
data = '<?xml version="1.0" encoding="UTF-8"?><blah></blah>'
response = self.client.post(reverse('my_url'),
data=data,
content_type='application/xml')
def my_view(request):
xml = request.body
You can use mocking. Some examples available here and in docs here
Updated
Kit, I think it's very depends on your test case. But in general you shouldn't use raw_post_data directly. Instead it's have to be patched like in example below:
from mock import Mock, MagicMock
class SomeTestCase(TestCase):
def testRawPostData(self):
...
request = Mock(spec=request)
request.raw_post_data = 'myrawdata'
print request.raw_post_data # prints 'myrawdata'
file_mock = MagicMock(spec=file)
file_mock.read.return_value = 'myfiledata'
request.FILES = {'myfile': file_mock}
print request.FILES['myfile'].read() # prints 'myfiledata'
The error message the interpreter is giving is correct. After you access the POST data via if request.FILES, you can no longer access the raw_post_data. If in your actual code (not the tests) you hit that line, it would error with the same message. Basically, you need two separate views for form-based POSTS and direct file POSTS.
I took this listing here
c = Client()
f = open('wishlist.doc')
c.post('/customers/wishes/', {'name': 'fred', 'attachment': f})
f.close()
Client is a special class for testing your views. This is the example of posting files to your view. It's part of Django testing framework.

How to serialize cleaned_data if it contains models?

I'm trying to serialize some form data so that I can stuff it into a hidden field until the user is ready to submit the whole form (think of a wizard).
I'm trying this:
print simplejson.dumps(vehicle_form.cleaned_data)
But I keep getting errors like this:
<VehicleMake: Honda> is not JSON serializable
Really I just need it to output the PK for "Honda".
This doesn't work either:
print serializers.serialize('json', vehicle_form.cleaned_data)
Gives:
'str' object has no attribute '_meta'
Presumably because it's iterating over the keys, which are all strings, whereas I think it expects a queryset, which I don't have.
So how do I do this?
Okay, so far I've come up with this:
from django.utils.simplejson import JSONEncoder, dumps, loads
from django.utils.functional import curry
from django.db.models import Model
from django.db.models.query import QuerySet
from django.core.serializers import serialize
class DjangoJSONEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, Model):
return obj.pk
elif isinstance(obj, QuerySet):
return loads(serialize('json', obj, ensure_ascii=False))
return JSONEncoder.default(self, obj)
json_encode = curry(dumps, cls=DjangoJSONEncoder)
json_decode = loads
Based on the answers I found [here][1]. Now I'm trying this:
json = json_encode(vehicle_form.cleaned_data)
data = json_decode(json)
vehicle = Vehicle(**data)
The first 2 lines work perfectly, but the 3rd results in an exception:
Cannot assign "3": "Vehicle.model" must be a "VehicleModel" instance.
Getting close! Not sure how to deal with this one though...
This is a bit of a hack, but I don't know of a better way:
try:
vehicle_data = simplejson.loads(request.POST['vehicle_data'])
except ValueError:
vehicle_data = []
vehicle_data.append(vehicle_form.raw_data())
request.POST['vehicle_data'] = simplejson.dumps(vehicle_data)
It grabs the JSON data from hidden field in your form and decodes it into a Python dict. If it doesn't exist, it starts a new list. Then it appends the new raw/uncleaned data and re-encodes it and dumps it into the hidden field.
For this to work you need to either make a copy of the POST data (request.POST.copy()) so that it becomes mutable, or hack it like I did: request.POST._mutable = True
In my form template I put this:
<input type="hidden" name="vehicle_data" value="{{request.POST.vehicle_data}}" />
And lastly, to access the raw data for a form I added these methods:
from django.forms import *
def _raw_data(self):
return dict((k,self.data[self.add_prefix(k)]) for k in self.fields.iterkeys())
def _raw_value(self, key, value=None):
if value is None:
return self.data[self.add_prefix(key)]
self.data[self.add_prefix(key)] = value
Form.raw_data = _raw_data
Form.raw_value = _raw_value
ModelForm.raw_data = _raw_data
ModelForm.raw_value = _raw_value
Since .data returns too much data (in fact, it just returns the POST data you initially passed in), plus it's got the prefixes, which I didn't want.

Django error serilaizing output of query into JSON

Hi
I am trying to use Django to make a page that will search a database fro a certain keyword, I have managed to search the database for the keyword, but now I need to serialize the data into a JSON formatted array so I can use it on the client side using JavaScript.
When I try to serialize my result array I get this error:
'dict' object has no attribute '_meta'
My code looks like this:
def SearchItems(request, itemName):
items_list = list(Item.objects.filter(name = itemName).values())
json_serializer = serializers.get_serializer("json")()
data = json_serializer.serialize(items_list, ensure_ascii=False)
return HttpResponse(data)
Any help would be greatly appreciated,
RayQuang
Instead of using serializer, trying doing this:
return HttpResponse(simplejson.dumps(items_list),'application/json'))
see this answer for more info
do not convert an object to the dict.
simply pass a queryset to the serializer:
json_serializer.serialize(Item.objects.filter(name=itemName), ensure_ascii=False)
alternatively, you can use json/cjson/anyjson serializer directly:
import anyjson
HttpResponse(anyjson.serialize(Item.objects.filter(name=itemName).values()), content_type="application/json")

Serializing Django Model Instances (querysets with values tag)

I am trying to serialize the following view
def headerimage(request):
service_view = list( Service_images.objects.filter(service='7'))
return render_to_response ('headerimage.html',{'service_view':service_view}, context_instance=RequestContext(request))
This is supposed to return JSON in the form shown below
{"folderList":
["with schmurps"],
"fileList":
["toto006.jpg",
"toto012.jpg",
"toto013.jpg"
]
}
However, The folder list can be one or in this case will be "7" given that is the title("folder") of the images.
After taking into account the answer below, I came up with
def headerimage(request):
service_view = Service_images.objects.filter(service='7')
image = serializers.serialize("json", service_view)
mini = list(serializers.deserialize("json", image))
return HttpResponse(image, mimetype='application/javascript')
however, I am still looking for the simplest way to do this
service_view = Service_images.objects.filter(service='7').values('image')
The problem is that the django serializer expects whole models
Service_images.objects.filter() will return a QuerySet object for you, so basically wrapping this into list() makes no sense...
Look at the docs: http://docs.djangoproject.com/en/dev/topics/serialization/#id2, and use LazyEncoder definied there.
I usually follow the below way, when the json format requirement does not match with my model's representation.
from django.utils import simplejson as json
def headerimage(request):
service_view = Service_images.objects.filter(service='7')
ret_dict = {
"folderList":
[sv.image.folder for sv in service_view],
"fileList":
[sv.image.file for sv in service_view]
}
return (json.dumps(ret_dict), mimetype="application/json")