TheLifeOfSteve
TheLifeOfSteve

Reputation: 3288

Replacing text with variables

I have to send out letters to certain clients and I have a standard letter that I need to use. I want to replace some of the text inside the body of the message with variables.

Here is my maturity_letter models.py

class MaturityLetter(models.Model):
default = models.BooleanField(default=False, blank=True)
body = models.TextField(blank=True)
footer = models.TextField(blank=True)

Now the body has a value of this:

Dear [primary-firstname],

AN IMPORTANT REMINDER…

You have a [product] that is maturing on [maturity_date] with [financial institution].

etc

Now I would like to replace everything in brackets with my template variables.

This is what I have in my views.py so far:

context = {}
if request.POST:
    start_form = MaturityLetterSetupForm(request.POST)
    if start_form.is_valid():
        agent = request.session['agent']
        start_date = start_form.cleaned_data['start_date']
        end_date = start_form.cleaned_data['end_date']
        investments = Investment.objects.all().filter(maturity_date__range=(start_date, end_date), plan__profile__agent=agent).order_by('maturity_date')
        inv_form = MaturityLetterInvestments(investments, request.POST)
        if inv_form.is_valid():
            sel_inv = inv_form.cleaned_data['investments']
            context['sel_inv'] = sel_inv
        maturity_letter = MaturityLetter.objects.get(id=1)
        
        context['mat_letter'] = maturity_letter
        context['inv_form'] = inv_form
        context['agent'] = agent
        context['show_report'] = True

Now if I loop through the sel_inv I get access to sel_inv.maturity_date, etc but I am lost in how to replace the text.

On my template, all I have so far is:

{% if show_letter %}
{{ mat_letter.body }} <br/>
{{ mat_letter.footer }}
{% endif %}

Much appreciated.

Upvotes: 0

Views: 461

Answers (4)

juliomalegria
juliomalegria

Reputation: 24921

I think this is the best way to do it. First, you have a file with your template, something like:

Dear {{primary-firstname}},
AN IMPORTANT REMINDER…
You have a {{product}} that is maturing on {{maturity_date}} with {{financial institution}}.
etc ...

So, your view will go something like:

from django.template.loader import render_to_string

# previous code ...
template_file = 'where/is/my/template.txt'
context_data = {'primary-firstname': 'Mr. Johnson',
                'product': 'banana',
                'maturity_date': '11-17-2011',
                'financial institution': 'something else'}
message = render_to_string(template_file, context_data)
# here you send the message to the user ...

So if you print message you'll get:

Dear Mr. Johnson,
AN IMPORTANT REMINDER…
You have a banana that is maturing on 11-17-2011 with something else.
etc ...

Upvotes: 2

Niels
Niels

Reputation: 41

You can use regular expression substitution with a callback. The advantage of this over a simple string replace or using django's template engine is that you also know when undefined variables are used (since you might not want to send out letters/emails like that :)

import re

body = """
Dear [primary-firstname],

AN IMPORTANT REMINDER...

You have a [product] that is maturing on [maturity_date] 
with [financial institution].

etc
"""

def replace_cb(m):
    replacements = {'primary-firstname': 'Gary',
                    'product': 'Awesome-o-tron2k',
                    'maturity_date': '1-1-2012',
                    'financial institution': 'The bank'}
    r = replacements.get(m.groups()[0])
    if not r:
        raise Exception('Unknown variable')
    return r 

new_body = re.sub('\[([a-zA-Z-_ ]+)\]', replace_cb, body)

Upvotes: -1

yurib
yurib

Reputation: 8147

use format strings:

>>> print "today is %(date)s, im %(age)d years old!" % {"date":"my birthday!","age":100}
today is my birthday!, im 100 years old!

Upvotes: 4

Krumelur
Krumelur

Reputation: 32497

One solution is to use Django's template engine on the body itself (as you do when rendering the page). I am sure there are security implications if the text is editable by users etc.

A simpler solution would be simple string replacement. For example, given what you have above:

for var, value in sel_inv.items:
    body = body.replace('[%s]' % var, value)

It's not the prettiest solution, but if your body template is fixed you need to do something like this.

Upvotes: 0

Related Questions