django template system, calling a function inside a model

I want to call a function from my model at a template such as:

class ChannelStatus(models.Model):
..............................
..............................


def get_related_deltas(self,epk):
mystring = ""
if not self.get_error_code_delta(epk):
return mystring
else:
for i in self.get_listof_outage():
item = i.error_code.all()
for x in item:
if epk == x.id:
mystring= mystring +" "+str(i.delta())
return mystring

And when I want to call this from the template: assume while rendering, I pass channel_status_list as

channel_status_list = ChannelStatus.objects.all()


{% for i in channel_status_list %}
{{ i.get_related_deltas(3) }}
{% endfor %}

This doesn't work, I am able to call a function that consumes nothing, but couln't find what to do if it has parameter(s)

Cheers

87764 次浏览

You can't call a function with parameters from the template. You can only do this in the view. Alternatively you could write a custom template filter, which might look like this:

@register.filter
def related_deltas(obj, epk):
return obj.get_related_deltas(epk)

So now you can do this in the template:

{% for i in channel_status_list %}
\{\{ i|related_deltas:3 }}
{% endfor %}

Another option is to define a property. See http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/ .

You write your function that can do pretty much anything you want. You make it a read only property. You call the property from the template.

Et voilà !!!!

If you find that there are too many properties running around everywhere or you have a template filter for every other method that you write, another solution was suggested on IRC thanks @FunkyBob. It's a little well, erm, funky but it is nice in certain cases.

  class MethodProxy(object):
"""For consolidating into 1 method the calling of methods with various single args
(suitable dictionary keys)


class MyModel(models.Model):
...


def magic(self, value):
# Free the ponies


def thing(self):
return MethodProxy(self.magic)


# Usage
>>> m = MyModel()
...
>>> m.thing['value'] == m.magic('value')


# template
\{\{ m.thing.value }}


"""


def __init__(self, method):
self.method = method
def __getitem__(self, key):
return self.method(key)

If the method doesn't require any arguments, you can use the @property decorator and access it normally in the template.

class ChannelStatus(models.Model):
...
@property
def function_you_want_as_property(self):
mystring = ""
...

For > 1 argument, use simple tags:

@register.simple_tag
def related_deltas(obj, epk, second_arg):
return obj.get_related_deltas(epk, second_arg)

Template:

{% for i in channel_status_list %}
{% related_deltas i 3 4 %}
{% endfor %}

(Note the change of syntax from \{\{ to {%)

Can take positional parameters (e.g. related_deltas i 3 second_arg=4 debug=true).