Reputation: 1003
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
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
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
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