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?
JSONParser. Parses JSON request content. request. data will be populated with a dictionary of data.
Use the JSONParser class methods to parse JSON-encoded content. These methods enable you to parse a JSON-formatted response that's returned from a call to an external service, such as a web service callout.
JSONRenderer. Renders the request data into JSON , using utf-8 encoding. Note that the default style is to include unicode characters, and render the response using a compact style with no unnecessary whitespace: {"unicode black star":"★","value":999}
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,)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With