55

I have the following generic class based views built with Django Rest framework (DRF)

class ExampleDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Example.objects.all()
    serializer_class = ExampleSerializer
    renderer_classes = (JSONRenderer, TemplateHTMLRenderer)

    def get(self, request, *args, **kwargs):

        response = self.retrieve(request, *args, **kwargs)
        if request.accepted_renderer.format == 'html':
            form = ExampleForm(data=response.data)
            return Response({'data': response.data, 'form': form}, template_name='example.html')

        return response

This view allow me to obtain both JSON data or HTML form from the same endpoint by specifying the format=json or html.

I would like to programmatically call that view to obtain the rendered HTML form from within another view in order to include this form in another page that will include more stuff.

Cœur
  • 34,719
  • 24
  • 185
  • 251
Etienne Desgagné
  • 2,954
  • 1
  • 26
  • 35

4 Answers4

38

I found the solution for this in the documentation... https://docs.djangoproject.com/en/1.7/topics/class-based-views/mixins/

Hint is from their example here:

class AuthorDetail(View):

    def get(self, request, *args, **kwargs):
        view = AuthorDisplay.as_view()
        return view(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        view = AuthorInterest.as_view()
        return view(request, *args, **kwargs)
user
  • 4,361
  • 4
  • 29
  • 58
  • 14
    Does not work. I get ```The `request` argument must be an instance of `django.http.HttpRequest`, not `rest_framework.request.Request`.``` – waqasgard Jan 30 '19 at 08:45
  • It's certainly possible both projects have diverged in how they treat things ... I haven't played with this in awhile. – user Jan 30 '19 at 14:55
  • 4
    Looks like someone (Greg Brown) proposed an edit that those calls should be `return view(request._request, *args, **kwargs)` -- maybe that is the "newer" way to do it, @waqasgard...worth trying I think. Leaving the answer as-is, since it matches the linked documentation and was valid for older versions of Django. – user Mar 27 '19 at 19:20
  • Here's the link to the 4.0 documentation: https://docs.djangoproject.com/en/4.0/topics/class-based-views/mixins/#avoid-anything-more-complex It has the same example. – Infinite Possibilities Dec 15 '21 at 14:24
29
html_from_view = ExampleDetail.as_view({'get': 'list'})(request).content

OR

html_from_view = ExampleDetail.as_view({'get': 'retrieve'})(request, pk=my_id).render().content
Etienne Desgagné
  • 2,954
  • 1
  • 26
  • 35
  • what is the request ? , and if I'm in one ipython shell – Sérgio Jun 02 '17 at 17:59
  • @Sérgio Read the question. The `request` is the same that was passed to the original view function / get method. If you are in a ipython shell, you have to use another approach. For example, you can emulate a http request using the django test client. https://docs.djangoproject.com/en/2.0/topics/testing/tools/#overview-and-a-quick-example – Håken Lid Jun 28 '18 at 12:05
  • 3
    The above works now, 5 years later, except use `request._request` instead of `request`. – Cloud Artisans Mar 17 '20 at 19:33
  • 1
    This solution works for the ViewSet but not APIView. The solution provided by JD Solanki below works for APIView. – Ketan Sahu Dec 07 '20 at 08:39
14

As of Django 2.2 and DRF 3.9.2 I am able to get response using below code.

response = UserItemsApiView.as_view()(request=request._request).data

Above example solves below issues:

  • The request argument must be an instance of django.http.HttpRequest, not rest_framework.request.Request
  • Instead of content, using data attribute gave me result from that view.
JD Solanki
  • 541
  • 4
  • 15
  • 2
    I get "b'{"detail":"CSRF Failed: CSRF token missing or incorrect."}'" when trying this, any idea why? – Thorvald Mar 10 '21 at 18:08
-10

If I'm understanding correctly, you need to get the result from view B, while inside view A.

Using the requests/urllib2 and json libraries should solve your problem (as specified in this answer).

To get the URL, you can use a combination of request.get_absolute_uri() and/or request.get_host() and django.core.urlresolvers.reverse.

Community
  • 1
  • 1
Jean Ventura
  • 27
  • 10