4

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.

asked Oct 14, 2015 at 11:47

3 Answers 3

3

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.

answered Oct 14, 2015 at 12:02

1 Comment

I updated fields in models, but not saved them, so there've not been any change in database, though updated models were properly passed to the template: for tf in tasks: template = Template(tf.task.description) context = Context({'temp': '123'}) tf.task.description = template.render(context)
1

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.

answered Oct 14, 2015 at 11:59

5 Comments

All student_var-like variables will come from database and corresponding model. What about the string, which comes from model as well? I need just to put it into Context as well?
I don't understand what you're asking. What string?
task.description string
But haven't I shown that in the answer? You pass that into the Template instantiation, it's not part of the context.
Okay, I'll try it and report my results. I just don't want to do rendering on my own
1

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
answered Oct 14, 2015 at 12:51

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.