Can I call a view from within another view?

DjangoDjango Views

Django Problem Overview


One of my view needs to add an item, along with other functionality, but I already have another view which specifically adds an item.

Can I do something like:

def specific_add_item_view(request):
    item = Item.objects.create(foo=request.bar)

def big_view(request):
    # ...
    specific_add_item_view(request)

Django Solutions


Solution 1 - Django

Sure, as long as when it's all said and done your view returns an HttpResponse object. The following is completely valid:

def view1(request):
    # do some stuff here
    return HttpResponse("some html here")

def view2(request):
    return view1(request)

If you don't want to return the HttpResponse from the first view then just store it into some variable to ignore:

def view1(request):
    # do some stuff here
    return HttpResponse("some html here")

def view2(request):
    response = view1(request)
    # do some stuff here
    return HttpResponse("some different html here")

Solution 2 - Django

View functions should return a rendered HTML back to the browser (in an HttpResponse). Calling a view within a view means that you're (potentially) doing the rendering twice. Instead, just factor out the "add" into another function that's not a view, and have both views call it.

def add_stuff(bar):
    item = Item.objects.create(foo=bar)
    return item

def specific_add_item_view(request):
    item = add_stuff(bar)
    ...

def big_view(request): 
    item = add_stuff(bar)
    ...

Solution 3 - Django

A better way is to use the template system. Combining ideas from @Seth and @brady:

def specific_add_item_view(request, extra_context_stuff=None):
    Item.objects.create()
    context_variables = {} # obviously want to populate this
    if extra_context_stuff:
        context_variables.update(extra_context_stuff)
    return render(request, 'app_name/view1_template.html', context_variables)

def bigger_view(request):
    extra_context_stuff = {'big_view': True}
    return specific_add_item_view(request, extra_context_stuff)

And your app_name/view1_template.html might contain a conditional template tag

{% if big_view %}
<p>Extra html for the bigger view</p>
{% endif %}

Solution 4 - Django

Without class based views:

def my_view(request):
    return call_another_view(request)

def call_another_view(request):
    return HttpResponse( ... )

With class based views:

def my_view(request):
    return CallAnotherView.as_view()(request)

class CallAnotherView(View):
    ...

Solution 5 - Django

You can do like this:

def foo(req):
  # code
def index(req):
  return foo(req)

Solution 6 - Django

My setup:

  • Python 3.9
  • Django 4

For class based views (all of them), this works:

class CheckoutPage(View):
    
    template_name = "checkout.html"
    def get(self, request):
        prices = ViewAllPrices.as_view()(request)
        return render(request, self.template_name, {'prices': prices})

Solution 7 - Django

If you do this:

def calledView(bar):
    ...
    return Response(...)

def base_view(request):
    resp = add_stuff(request)
    ...

You will probably get this error:

> The request argument must be an instance of > django.http.HttpRequest, not rest_framework.request.Request.

So you should do this instead:

def calledView(request):
    ...
    return Response(...)

def base_view(request):
    resp = add_stuff(request._request)
    ...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionjohn2xView Question on Stackoverflow
Solution 1 - DjangobradyView Answer on Stackoverflow
Solution 2 - DjangoSethView Answer on Stackoverflow
Solution 3 - DjangohobsView Answer on Stackoverflow
Solution 4 - DjangoGuilherme IazzettaView Answer on Stackoverflow
Solution 5 - DjangoOrozboy JigitView Answer on Stackoverflow
Solution 6 - DjangoArindam RoychowdhuryView Answer on Stackoverflow
Solution 7 - DjangoPaul BénéteauView Answer on Stackoverflow