skip to Main Content

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?

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search