mdgsec
mdgsec

Reputation: 83

Django rest serialization - Passing JSON to Javascript

Disclaimer - Django noob, especially REST Framework. I'm trying to create an app that for this purposes passes JSON to the template. I figured Django Rest would be ideal.

I have set up a user profile so the user can select various attributes (works fine), and now want to pass a JSON of all the user's selections to template. Think of it as a "my profile" page.

View:

        profile = Profile.objects.filter(user=request.user)
        serializer = ProfileSerializer(profile, many=True)
        myteam = JsonResponse(serializer.data, safe=False)

        print(myteam.content) ## to see what's being passed

        context = {'myteam': myteam.content}

        return render(request, 'main/myteam.html', context)

Template:

<script>
console.log({{myteam}});
<\script>

Django server output:

b'[{"user": "DAVE", "GK1": {"id": 1001, "ShortName": "J. Strummer", "Club": "CLUB", "Shirt": "SHIRT.png", "ShortClub": "ETC", "ShortPos": "FW", "CurrentVal": "10", "TotalPoints": 1}, "GK2": {"id": 320, "ShortName": "D. Jones", "Club": "CLUB2", "Shirt": "ETABE.png", "ShortClub": "ETABE", "ShortPos": "GK", "CurrentVal": "4.5", 

Template - Google Chrome JS console:

Uncaught SyntaxError: Invalid or unexpected token

Template - Chrome details:

console.log(b&#39;[{&quot;user&quot;: &quot;mikey&quot;, &quot;GK1&quot;: {&quot;id&quot;: 1001, &quot;ShortName&quot;: &quot;J. Strummer&quot;, &quot;Club&quot;: &quot;ETC&quot;, &quot;Shirt&quot;: &quot;SHIRT.png&quot;, &quot;ShortClub&quot;: &quot;ETC&quot;, &quot;ShortPos&quot;: &quot;FW&quot;, &quot;CurrentVal&quot;: &quot;10.0&quot;, &quot;TotalPoints&quot;: 1},  // lot's more of this

Noob Conclusion:

I don't seem to be getting a "clean" JSON object passed to the template from the server. Possibly due to the b'[ .... is this bytes literal?

Perhaps I should be using another method to pass the JSON to the template?

TWIST - in my testing I followed the REST tutorial and was able to setup a simple view which returned JsonResponse:

player = Player.objects.all()
serializer = PlayerSerializer(player, many=True)
return JsonResponse(serializer.data, safe=False)

Now if you go to this url mapping it displays in browser a perfect JSON example. I don't see why there should be a difference between

myteam = JsonResponse(serializer.data, safe=False)

and

return JsonResponse(serializer.data, safe=False)

I've been stuck on this on and off for literally days now so any help would be hugely appreciated.

Upvotes: 1

Views: 1692

Answers (2)

user9245558
user9245558

Reputation:

I believe you may need to do this:

    from rest_framework.renderers import JSONRenderer

    profile = Profile.objects.filter(user=request.user)

    serializer = ProfileSerializer(profile, many=True)

    content = JSONRenderer().render(serializer.data)

    return JsonResponse(content)

Or this:

    from rest_framework.renderers import JSONRenderer

    profile = Profile.objects.filter(user=request.user)

    serializer = ProfileSerializer(profile, many=True)

    return JsonResponse(serializer.data)

Rather than creating a JsonResponse object and passing it back through context.

There is another alternative, however, to the above as you'll want your endpoint to be extremely flexible.

Such API querying functionality is available from a 3rd-party package. I use this a lot, and find it works really well:

pip install djangorestframework-queryfields

Declare your serializer like this:

from rest_framework.serializers import ModelSerializer
from drf_queryfields import QueryFieldsMixin

class MyModelSerializer(QueryFieldsMixin, ModelSerializer):
    ...

Then the fields can now be specified (client-side) by using query arguments:

GET /identities/?fields=id,data

Exclusion filtering is also possible, e.g. to return every field except id:

GET /identities/?fields!=id

Upvotes: 3

Daniel Roseman
Daniel Roseman

Reputation: 599630

There are a few things going on here.

Firstly, you have taken the rendered output of a response and passed the content back into a template. This isn't the right thing to do; you should skip the JsonResponse altogether and pass serializer.data into a renderer before sending it to the template.

    serializer = ProfileSerializer(profile, many=True)
    data = JSONRenderer().render(serializer.data)
    context = {'myteam': data}
    return render(request, 'main/myteam.html', context)

Secondly, the encoding is due to Django templates' automatic HTML escaping. You should mark your JSON as safe.

console.log({{ myteam|safe }});

Upvotes: 2

Related Questions