Is there a way to send with json (or anything else other than render) an object_list made with paginator? The browser is making a getjson jquery request and the views.py function is supposed to return the object. The reason I want to return a json object rather than render a new page is because I don't want the page to reload
The following views.py code:
searchresults = form.search()#this is a call to a haystack form template
results = Paginator(searchresults, 20)
page = results.page(1)
return HttpResponse(json.dumps(page), content_type='application/json')
Gets this error:
TypeError: <Page 1 of 1> is not JSON serializable
Just use django serialization https://docs.djangoproject.com/en/dev/topics/serialization/
from django.core import serializers
...
return HttpResponse(serializers.serialize("json", [q.object for q in results.page(1).object_list]), content_type='application/json')
You need to create a dictionary that is serializable as #evilx commented or make your own Json by hand.
Related
I have a function in my views.py which returns JSON data, what I have in mind is rendering a HTML page from that data.
The same question can also be associated with data returned from rest API generic views returning JSON data.
I didn't understand your concern, but you can send the json data to your template using json.dumps()
response_data = {}
response_data['name'] = 'test'
response_data['message'] = 'Hi test'
render(request, "test.html", {'json_data': json.dumps(response_data)})
Now, you can access json_data in your template
I was going through django rest framework tutorial on serialization in which I got stuck at JSONRenderers and JSONParsers.Below is the code mentioned there:
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from django.utils.six import BytesIO
snippet = Snippet(code='foo = "bar"\n')
snippet.save()
snippet = Snippet(code='print "hello, world"\n')
snippet.save()
serializer = SnippetSerializer(snippet)
serializer.data
# {'pk': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
content = JSONRenderer().render(serializer.data)
content
# '{"pk": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
stream = BytesIO(content)
data = JSONParser().parse(stream)
I know JSONParser is used for deserializing the data and JSONRenderer is used for serializing it , but I still don't have a sound understanding of the difference between serializing and deserializing of a data. Can someone provide me a clear understanding of this.(Answer with an example is highly appreciated.)
And also how does JSONRenderer and JSONParser work?
I will start with viewsets. View and viewsets are classes in DRF, where most of application logic happens.
Eg. ModelViewSet is class responsible for CRUD operations in response to POST, PUT, PATCH, GET, DELETE HTTP methods.
Lets take look at default create method from https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py this method create instance of your model, from data (if they are valid) send via HTTP POST method and persist them to database.
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
This is whats happening here.
self.get_serializer() create new instance of serializer (you set serializer class before), it takes request.data as argument. request.data is (this is importent) dictionary. Dictionary is generic python data structure.
serializer.is_valid() method checks if request.data are valid. If yes you can access serializer.data - also a dictionary.
serializer.save() method creates and persist actual instance of your model (Snippet) to database.
You can directly access instance like this
instance = serializer.save()
Then you return Response object populated with serializer.data back to client.
As you can see, there is no Form data,JSON, XML, HTML etc. in viewset. You work with python data types and serializer is reponsible of "translating" dictionary to instance of your specific model and backwards.
But client send data (in your case) in HTTP request in form of JSON.
JSONParser is responsible of converting JSON to dictionary. Parsing is implemented inside request class https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/request.py , please notice that is not standard django HttpRequest model.
You can set multiple parsers, then request will choose proper one according to HTTP request header: Content-type.
Second thing is, you have to return serializer.data back to client in form of JSON, not dictionary. Thats what JSONRenderer does. It convert dict to JSON and its implemented inside Response class https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/response.py. Also you can set multiple renderers and then the proper one is choose according to accepted media type http header.
Example of full viewset definition might be:
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
renderer_classes = (JSONRenderer, )
parser_classes = (JSONParser,)
I'm working in Django 1.8 and having trouble finding the modern way to do this.
This is what I've got, based on Googling and this blog post:
results = PCT.objects.filter(code__startswith='a')
json_res = []
for result in results:
json_res.append(result.as_dict())
return HttpResponse(json.dumps(json_res), content_type='application/json')
However this gives me 'PCT' object has no attribute 'as_dict'.
Surely there must be a neater way by now?
I was wondering if it was possible to use JSONResponse but frustratingly, the docs give no example of how to use JSONRespose with a queryset, which must be the most common use case. I have tried this:
results = PCT.objects.filter(code__startswith='a')
return JsonResponse(results, safe=False)
This gives [<PCT: PCT object>, <PCT: PCT object>] is not JSON serializable.
Simplest solution without any additional framework:
results = PCT.objects.filter(code__startswith='a').values('id', 'name')
return JsonResponse({'results': list(results)})
returns {'results': [{'id': 1, 'name': 'foo'}, ...]}
or if you only need the values:
results = PCT.objects.filter(code__startswith='a').values_list('id', 'name')
return JsonResponse({'results': list(results)})
returns {'results': [[1, 'foo'], ...]}
use values() to return a querydict, and pass that to json.dumps
values = PCT.objects.filter(code__startswith='a').values()
return HttpResponse(json.dumps(values), content_type='application/json')
https://docs.djangoproject.com/en/1.8/ref/models/querysets/#values
Most of these answers are out of date. Here's what I use:
views.py (returns HTML)
from django.shortcuts import render
from django.core import serializers
def your_view(request):
data = serializers.serialize('json', YourModel.objects.all())
context = {"data":data}
return render(request, "your_view.html", context)
views.py (returns JSON)
from django.core import serializers
from django.http import HttpResponse
def your_view(request):
data = serializers.serialize('json', YourModel.objects.all())
return HttpResponse(data, content_type='application/json')
Take a look at Django's serialization framework. It allows not only the XML format, but also JSON and YAML.
The accepted answer, using JsonResponse, is nice and simple. However, it does not return complete objects.
An alternative is to use Django's serializers. Here's an example copied verbatim from the admin actions documentation:
...
response = HttpResponse(content_type="application/json")
serializers.serialize("json", queryset, stream=response)
return response
This is very similar to what happens in Django's JsonResponse, as can be seen in the source.
The main difference is that JsonResponse calls json.dumps() directly, and does not know how to handle querysets, whereas the example above uses serializers.serialize('json', ...), which does know how to handle querysets, and returns complete objects that can also be de-serialized later on.
If you want to save directly to file (using content-disposition: attachment to open a save dialog in the browser), you could use a FileResponse, for example:
...
data = serializers.serialize('json', queryset)
return FileResponse(
io.BytesIO(data.encode('utf-8')),
content_type='application/json',
as_attachment=True,
filename=f'{queryset.model.__name__.lower()}-objects.json'
)
I am trying to serialize my form into the json format. My view:
form = CSVUploadForm(request.POST, request.FILES)
data_to_json={}
data_to_json = simplejson.dumps(form.__dict__)
return HttpResponse(data_to_json, mimetype='application/json')
I have the error <class 'django.forms.util.ErrorList'> is not JSON serializable. What to do to handle django forms?
Just in case anyone is new to Django, you can also do something like this:
from django.http import JsonResponse
form = YourForm(request.POST)
if form.is_valid():
data = form.cleaned_data
return JsonResponse(data)
else:
data = form.errors.as_json()
return JsonResponse(data, status=400)
JsonResponse: https://docs.djangoproject.com/en/dev/ref/request-response/#jsonresponse-objects
Form.cleaned_data: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.cleaned_data
Form.errors.as_json(): https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.errors.as_json
You may want to look at the package called django-remote-forms:
A package that allows you to serialize django forms, including fields
and widgets into Python dictionary for easy conversion into JSON and
expose over API
Also see:
How to cast Django form to dict where keys are field id in template and values are initial values?
I have code that looks like this:
def client = new groovyx.net.http.RESTClient('myRestFulURL')
def json = client.get(contentType: JSON)
net.sf.json.JSON jsonData = json.data as net.sf.json.JSON
def slurper = new JsonSlurper().parseText(jsonData)
However, it doesn't work! :( The code above gives an error in parseText because the json elements are not quoted. The overriding issue is that the "data" is coming back as a Map, not as real Json. Not shown, but my first attempt, I just passed the parseText(json.data) which gives an error about not being able to parse a HashMap.
So my question is: how do I get JSON returned from the RESTClient to be parsed by JsonSlurper?
The RESTClient class automatically parses the content and it doesn't seem possible to keep it from doing so.
However, if you use HTTPBuilder you can overload the behavior. You want to get the information back as text, but if you only set the contentType as TEXT, it won't work, since the HTTPBuilder uses the contentType parameter of the HTTPBuilder.get() method to determine both the Accept HTTP Header to send, as well was the parsing to do on the object which is returned. In this case, you need application/json in the Accept header, but you want the parsing for TEXT (that is, no parsing).
The way you get around that is to set the Accept header on the HTTPBuilder object before calling get() on it. That overrides the header that would otherwise be set on it. The below code runs for me.
#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.6')
import static groovyx.net.http.ContentType.TEXT
def client = new groovyx.net.http.HTTPBuilder('myRestFulURL')
client.setHeaders(Accept: 'application/json')
def json = client.get(contentType: TEXT)
def slurper = new groovy.json.JsonSlurper().parse(json)
The type of response from RESTClient will depend on the version of :
org.codehaus.groovy.modules.http-builder:http-builder
For example, with version 0.5.2, i was getting a net.sf.json.JSONObject back.
In version 0.7.1, it now returns a HashMap as per the question's observations.
When it's a map, you can simply access the JSON data using the normal map operations :
def jsonMap = restClientResponse.getData()
def user = jsonMap.get("user")
....
Solution posted by jesseplymale workes for me, too.
HttpBuilder has dependencies to some appache libs,
so to avoid to add this dependencies to your project,
you can take this solution without making use of HttpBuilder:
def jsonSlurperRequest(urlString) {
def url = new URL(urlString)
def connection = (HttpURLConnection)url.openConnection()
connection.setRequestMethod("GET")
connection.setRequestProperty("Accept", "application/json")
connection.setRequestProperty("User-Agent", "Mozilla/5.0")
new JsonSlurper().parse(connection.getInputStream())
}