Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include JSON from Django Rest Framework in an HTML template

I am trying to do something very simple but haven't found how to do it yet.

I have a model and an endpoint returning a JSON array reprenseting the instances of this model with Django Rest Framework. I want to include the JSON in an HTML template (for SEO and for fast initial data loading). Something like

<script>
    var data = {% json_from_django_rest_framework "mymodel" %};
</script>

Is there an easy way to do this? Should I just go a different way?

like image 383
Rems Avatar asked Jul 08 '26 07:07

Rems


2 Answers

Another way of doing this, which gets around rendering the view.

In your views.py;

class FooDetailView(DetailView):
    model = Foo
    template_name = 'foo/detail.html'

    def get_context_data(self, **kwargs):
        bars = []
        for bar in self.object.bars.all():
            bars.append(BarSerializer(bar).data)

        kwargs['bars'] = JSONRenderer().render(bars)

        return super(FooDetailView, self).get_context_data(**kwargs)

And in your template;

<script>
    var bars = {{ bars|safe }};
</script>  

It should really go without saying that you should pay attention to potential performance issues with this approach, ie.. perhaps it's best to paginate bars.

like image 180
alexhayes Avatar answered Jul 10 '26 23:07

alexhayes


As discussed in the comments, here is an example of how to reuse the result from your api endpoint in a normal Django view by using Django's resolve function.

views.py

import json
from django.core.urlresolvers import resolve
from django.views.generic.base import View    

class FooView(View):
    def get(self, request):
        # optional stuff in your view...

        ##
        # Resolving another Django view programmatically
        ##
        rev = '/path/to/api/endpoint/'  # or use reverse()
        view, vargs, vkwargs = resolve(rev)
        vkwargs['request'] = request
        res = view(*vargs, **vkwargs)

        c = Context({
            'data': json.dumps(res.data)
        })

        # Now the JSON serialized result from the API endpoint
        # will be available in the template variable data.
        return render(request, 'my-app/my-template.html', c)

my-template.html

<script>
    var data = {{ data }};
</script>

Note 1: Instead of hardcoding the path in rev = '/path/to/api/endpoint/' it is better to reverse() the url, but I left it out to remove that as a source for errors. If you are going this direction, here is a list of the default url names provided by DRF

Note 2: The snippet would benefit from exception handling, like making sure that res returned 200, has the data property, etc.

like image 45
sthzg Avatar answered Jul 11 '26 00:07

sthzg