Reputation: 83
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'[{"user": "mikey", "GK1": {"id": 1001, "ShortName": "J. Strummer", "Club": "ETC", "Shirt": "SHIRT.png", "ShortClub": "ETC", "ShortPos": "FW", "CurrentVal": "10.0", "TotalPoints": 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
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
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