vladfau
vladfau

Reputation: 1003

Django: variable in variable in templates

Let's assume the following situation. In my database (model) I have a field of description of the task for students. Each student should have their own variant of some variables in the task. So, I save the following model named task in the database:

 id | name    | description                                  |
 ---+---------+----------------------------------------------+
  1 | Simple  | This is first task. Answer is {{student_var}}|

Method for the view is simple (TeamFlag is a table to correlate teams and tasks:

def render_team(request, team):
    tasks = TeamFlag.objects.filter(team=team)
    return render(request,
                  'team.html',
                  dict({'team': team,
                        'tasks': tasks,
                        'student_var': 'foo',
                        }))

In my template:

{% for team_task in tasks %}
    <li class="item">
        <h6>{{ team_task.task.name }}</h6>
        <div class="task-content">{% autoescape off %}
                                  {{team_task.task.description }}
                                  {% endautoescape %}</div>

As the result I see:

 This is first task. Answer is {{student_var}}

Is there any way in Django to pre-process variables, which are inside the string and pass processed HTML string to the view inside the template, basing on variables (I plan to keep variables in database in K-V format in table with fields like: id, key, value, team_id, task_id).

Generally, I would like to have some method like process_template(html_string, kv-data), which returns processed HTML string or something similar. I heard about custom filters for the templates, but I'm not sure, whether it's the case or not.

UPD: I successfully added the following code:

tasks = TeamFlag.objects.filter(team=team)
for tf in tasks:
    data = TaskData.objects.filter(team=team, task=tf.task)
    tf.task.description = Template(tf.task.description).render(
        Context(dict(zip([x.key for x in data],
                         [x.value for x in data]))))

However, Django now ignores layout in tf.task.description. My new description looks like:

I have some {{temp}} <b>here</b> and it's {{temp2}}

It's being rendered, I can see it in source code of the page, but actually nothing happens.

UPD2: Seems to be CSS problem. Question closed.

Upvotes: 4

Views: 3440

Answers (3)

Tarun Behal
Tarun Behal

Reputation: 918

You can create a simple tag and use that in django template like below:

{% my_custom_filter team_task.task.description %}

from django.template import Context, Template

@register.simple_tag(name='my_custom_filter', takes_context=True)
def my_custom_filter(context, val):
    template = Template(val)
    context = Context(context)
    final_val = template.render(context)
    return final_val

Upvotes: 1

Christian Witts
Christian Witts

Reputation: 11585

For a helper method, you could create something with Template and Context

from django.template import Template, Context

def process_template(tasks, student_var):
    new_tasks = []
    for team_task in tasks:
        template = Template(team_task.task.description)
        context = Context({'student_var': student_var})
        rendered_template = template.render(context)
        team_task.task.description = rendered_template
        new_tasks.append(team_task)
    return new_tasks

def render_team(request, team):
    tasks = process_template(TeamFlag.objects.filter(team=team))

You can take a look at the documentation for more info.

Upvotes: 3

Daniel Roseman
Daniel Roseman

Reputation: 600026

The template processor is just code. It accepts a string, parses it, and populates it according to the context it is given. The string can just as easily come from the database as from a file on disk.

At its root it is as simple as:

from django.template import Template, Context

tpl = Template(task.description)
output = tpl.render(tpl, Context({'student_var': 'foo'}))

Where you put this is up to you. It could be a model method, or a template filter. One question you don't answer is where the variables are coming from; if there is only student_var, you can pass that in to the filter explicitly; if not you'll have to work out where to get them from.

Upvotes: 1

Related Questions