Home » Odeon Blogs » Liviu, Agile Bear »

Calling instance methods with arguments inside Django templates

Calling instance methods with arguments inside Django templates

What to do in those strange situations where you need to use an instance's method, which needs at least one argument, in the template? You can't always generate the values from the views.py and send them in variables, imagine a for loop where you need to get it.

The easy way to do it is using Django filters.

Three solutions. Pick the one that fits your needs.

There are three solution presented in this article:
1. calling one method only which requires one argument;
2. calling one method only which requires more string/int arguments;
3. calling any method which requires one or more arguments.

The no argument case is a simple {{ instance.method }} call, so there is no point discussing it.

To illustrate our examples, we'll use the following model and call the template_call() method:

  1. from django.db import models
  2. class SomeObject(models.Model):
  3. some_field = models.TextField()
  4. def template_call(self, *args):
  5. """ this is the method that will be called """
  6. return ", ".join(args)

Calling one method only which requires one argument

The simplest case. We only need to call one method which requires only one argument. A normal filter is enough since we can hardcode the method's name in it and send the attribute as a parameter:

  1. #template_filters.py
  2. from django import template
  3. register = template.Library()
  4. @register.filter
  5. def test_simple_template_call(instance, args):
  6. """
  7. allows only one argument for one exact method
  8. """
  9. return instance.test_template_call(args)
  10. # template usage
  11. {{ instance|test_simple_template_call:"value1" }}
  12. # output
  13. value1

Calling one method only which requires more string/int arguments

This approach is similar to the one before, the difference is that the arguments will be passed as key=value pairs separated by '&'. To resolve them, we will use the same class Django uses to parse query strings out of URL's, since it is the same structure.

  1. #template_filters.py
  2. from django.http import QueryDict
  3. @register.filter
  4. def test_advanced_template_call(instance, args):
  5. """
  6. allows more arguments like a query dict:
  7. var_name=value&var_name2=value
  8. """
  9. qd = QueryDict(args)
  10. return instance.test_template_call(*qd.values())
  11. # template usage
  12. {{ instance|test_advanced_template_call:"var_1=value1&var_2=value2" }}
  13. # output (note the values order)
  14. value2, value1

Calling any method which requires one or more arguments

This is the complex one. You can send any number of arguments and specify which method to call. For this to happen we need not one, but two filters: one to set the arguments in the instance's attributes and one to name the method. The order the filters are called is essential: first the arguments and then the method.

  1. #template_filters.py
  2. @register.filter
  3. def template_args(instance, arg):
  4. """
  5. stores the arguments in a separate instance attribute
  6. """
  7. if not hasattr(instance, "_TemplateArgs"):
  8. setattr(instance, "_TemplateArgs", [])
  9. instance._TemplateArgs.append(arg)
  10. return instance
  11. @register.filter
  12. def template_method(instance, method):
  13. """
  14. retrieves the arguments if any and calls the method
  15. """
  16. method = getattr(instance, method)
  17. if hasattr(instance, "_TemplateArgs"):
  18. to_return = method(*instance._TemplateArgs)
  19. delattr(instance, '_TemplateArgs')
  20. return to_return
  21. return method()
  22. # template usage
  23. {{ instance|template_args:"value1"|template_args:"value2"|template_args:"value3"|template_method:"test_template_call" }}
  24. # output
  25. value1, value2, value3

With all this filters, you can choose the one that best fits your needs without over doing it.


Category: Django


Tagged as: django template tag

Discussion

  1. thanks for this. very usefull article.




Leave a Comment :

(required)


(required)




(required)




(required)






Leave a Comment


Page generated in: 0.23s