Anand
Anand

Reputation: 139

How to Pass a Python Variable to a Template in another app in Django

I have views in app_1 which returns a dictionary and I want to pass it in the html in another app called app_2. I tried using {{dic_name.value_1}} and also like {{app_name:dic_name.value_1}}, but it didn't work.

-app_1 
     --urls.py
     --views.py
    -app_2
     --templates
       --app_2
         -- app_2.html

my view in app_1

def index(request):
  user_info={}
  user_info['name']= 'joe'
  user_info['age'] = 23
  return JsonResponse(user_info)

my Html in app2 is like

<body>
 <h1>Name</h1>: {{user_info.name}}
 <h1>Ange</h1>: {{user_info.age}}
</body>

Can anyone help to solve this problem. Thanks

Upvotes: 0

Views: 934

Answers (1)

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

First a couple comments:

I have views in app_1 which returns a dictionary

Nope, it returns an HTTP response (with json content and application/json as content-type).

and I want to pass it in the html in another app called app_2.

That's just not how it works. A Django view returns a HTTP response, period (wether the response's body contains HTML and wether this HTML has been built using a template are totally irrelevant here).

I tried using {{dic_name.value_1}} and also like {{app_name:dic_name.value_1}}, but it didn't work.

Programming by accident never really works. You'll get better results - and you'll get them faster - by understanding how things work and do the right thing right from the start.

NB : Sorry if this looks a bit patronizing, please don't take it as a personal offense, I'm really trying to help you with those comments.

Now for the proper answer:

For the general case, when you have a piece of data (an object, a list, a dict, whatever) that you want to make accessible to different unrelated templates, you mainly have two solution:

  1. a context processor
  2. a custom templatetag

A context processor will be invoked for all templates rendering (well, almost, cf the doc), so it's the right solution when you want this "piece of data" to be available everywhere "out of the box". The downside is that you'll get a performance hit for each and every template. Also, a context processor only has access to the request - it can't access the template's context.

A custom templatetag is only executed when called from a template, so it's a better option if the "piece of data" you want is costly to build and is only used in a few templates. Also it can take arguments from the template, including the full context.

From a maintainability / reusability POV, whether you go for a processor or templatetag, it's usually better to factor out the code producing the desired value(s) into a dedicated utility function and to call that functions from the processor or tag.

In your case, your app_1.views.index_view returns a JsonResponse, so factoring out this part of code is indeed the best solution:

app_1/utils.py:

def get_user_info():
    return {"name": "Joe", "age": 42}

app_1/views.py:

from app_1.utils import get_user_info

def index(request):
    user_info = get_user_info()
    return JsonResponse(user_info)

app_1/templatags/app_1.py:

# you'll need this if using python 2.7.x
# else the import will fail
from __future__ import absolute_imports
from django import template
from app_1.utils import get_user_info

register = template.Library()

@register.simple_tag
def user_info():
    return get_user_info()

app2 template.html

{% load user_info from app_1 %}

{% user_info as ui %}
<dl>
  <dt>Name</dt><dd>{{ ui.name }}</dd>
  <dt>Age</dt><dd>{{ ui.age }}</dd>
</dl> 

This is of course a dumbed down example (and it might have a couple bugs, as all made up examples) and your real code will certainly be a bit more involved, but this should at least get you started.

Upvotes: 1

Related Questions