3

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?

4
  • How do you want to render / create this template? Obviously, the DRF endpoint will deliver you some data (in this case in JSON). To statically render that JSON on the server, you could make a normal Django view that delivers your template. From within that view you could request the data from the DRF endpoint. I guess later on some Javascript on the frontend will take control over your webapp and this is why you need the REST API in the first place? Commented Apr 20, 2015 at 20:25
  • Yes I can serialize the JSON in python in the view. I was hopping there was a more straightforward way to do this in the template directly. Indeed, later on the javascript will make further requests to the REST endpoint. Commented Apr 21, 2015 at 7:12
  • Is your goal to avoid an additional view altogether or just to avoid having to create the same output that the DRF endpoint already provides in this additional view? In the latter case, you could use Django's resolve helper to reuse the JSON-output from DRF within your view and thus still keep it DRY. (I could provide an example for that) Commented Apr 21, 2015 at 7:41
  • The latter. Yes an example would be nice. Commented Apr 21, 2015 at 7:55

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I much prefer this answer as it doesn't require you to create a view to the serializer if you don't intend the data to be exposed via a viewset
3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.