views:

344

answers:

2

I've got a filter currency, which takes a value in USD and converts it to a currency (either USD or GBP). The currency to convert to is stored in the session, but filters don't take RequestContext, so I can't grab it straight from there.

Is there a better way than passing the relevant session element into the template, and from the template into the filter as an argument? Whilst this approach is working, it seems fairly horrible, and I'm likely to end up passing the currency to (almost) every template.

My filter currently looks something like this:

def currency(value, currency):
    if currency == 'usd':
       val = '$%.2f' % value
       return mark_safe(val)

    d = Decimal(value)
    val = '£%.2f' % (d*Decimal('0.63'))

    return mark_safe(val)
+4  A: 

If you create a template tag instead of a filter, you are given the context to work with (which contains the request). http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags

Adam
@Adam - maybe I'm being thick, but I can't see in those docs how to get access to session variables from within custom template tags. Could you give me an example or point out what I'm missing?
Dominic Rodger
Ah - digging around it appears to be passed as the first argument to the tag (just found an example which adds a class to links matching a regular expression, which looks (a) useful and (b) adaptable - http://gnuvince.wordpress.com/2007/09/14/a-django-template-tag-for-the-current-active-page/).
Dominic Rodger
Right, the context is a standard parameter of the render method on the template tag node. If you need a further specific example, I'm sure I could muster one up.
Adam
Well, looking at the example in the URL posted, it's not quite the same since the author is explicitly passing the request. If you write the template tag as a mixture of a compilation and renderer methods, the context is passed without explicitly doing anything from the template.
Adam
A: 

This can be done using a filter. First make sure that you have "django.core.context_processors.request" in you TEMPLATE_CONTEXT_PROCESSORS. If you don't, you can add this to your settings.py file:

TEMPLATE_CONTEXT_PROCESSORS += (
    "django.core.context_processors.request"
)

Then in your template, your filter will look like this (assuming your session variable is named 'currency_type'):

{{value|currency:request.session.currency_type}}

Or is something like this what you are considering fairly horrible?

Zach
He is; Look at what he is doing, that filter describes exactly what you are telling.
D4V360
I thought he might be complaining about the process of having to explicitly pass the variable through the view. This will make it available automatically. I can also post an example of using a template tag with takes_context=True in the decorator
Zach