How to Call Function That Takes an Argument in a Django Template

How to call function that takes an argument in a Django template?

You cannot call a function that requires arguments in a template. Write a template tag or filter instead.

Call methods in Django Template

Yes, as commented above, this question has duplicates (How to call function that takes an argument in a Django template?).

What you want to do is create a custom template tag (https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags) like so...

# template
<p>Can Edit: {% can_edit_report user_id report_id %}.</p>

# template_tags.py
from django import template

def can_edit_report(parser, token):
try:
# tag_name is 'can_edit_report'
tag_name, user_id, report_id = token.split_contents()
# business logic here (can user edit this report?)
user = User.objects.get(pk=user_id)
report = Report.objects.get(pk=report_id)
can_edit = user.can_edit_report(report)
except ValueError:
raise template.TemplateSyntaxError("%r tag requires two arguments" % token.contents.split()[0])
return can_edit

Calling function with variable from view template, django

Sadly, you cannot pass arguments to functions in Django templates.

You ought to write your own template tags.

Use this answer as reference :-)

Calling Python function in Django template

What do you mean by "it doesn't like the split"? How does it manifest its dislike?

If I remember correctly, you can not pass any arbitrary arguments to methods, that are called from the django template and the identifiers, that can be used in the templates can only consist of a-z, A-Z, 0-9, underscores and dots (where dots signify lookup: dictionary->attribute->method->list-index).

There are at least four ways to achieve what you want:

  • make the appropriately prepared data available as an attribute of your model (or whatever that is), by pre-processing it
  • make the data available as a method of your model and make sure, that the method takes no required arguments, besides self
  • populate the model instances in the view

     for newsletter in newsletters:
    setattr(newsletter, 'basepath',
    newsletter.NewsletterPath.split('/')[-1])

    (or something along these lines)

  • implement a custom filter tag, that will handle the split (easier, than you might think)

How to call a function in template which is defined in a Django model?

You can directly annotate the aggregation, for example:

Invoice.objects.aggregate(amount = Sum('selling_price'))

The resulting dictionary will have a key called amount. If no such alias were specified, it would be the rather long selling_price__sum

Since it returns a dict, you can get the value through:

class YourModel(models.Model):

@property
def get_total(self):
amount = Invoice.objects.aggregate(amount = Sum('selling_price'))['amount']
return amount

# template
{{ item.get_total }} would only get amount value out, not dict

BTW:

Adding extra manager methods is the preferred way to add “table-level”
functionality to your models. (For “row-level” functionality – i.e.,
functions that act on a single instance of a model object

Aggregation is a table level function, since it calculate the sum of multiple objects, which is better defined as manager method instead at model instance level.

class InvoiceManager(models.Manager):
def get_total(self):
return self.aggregate(amount = Sum('selling_price'))['amount']

class Invoice(models.Model):
product_name = models.CharField(max_length=255)
purchase_date = models.DateTimeField(auto_now=True)
cost_price = models.IntegerField()
selling_price = models.IntegerField()
# customized manager
objects=InvoiceManager()

Views

def your_view(request):
...
context = {
'query_result': Invoice.objects.all()
'amount': Invoice.objects.get_total()
}
return render(request, 'index.html', context)

Function with arguments in a template. Django

It looks as though you are confusing client-side code (JavaScript) with server-side (Django).

To get the relevant user ID submitted you could add an additional hidden field to the form:

{% for user in following % }
<form method="post" action="{% url views.remove_relationship %}">
{% csrf_token %}
<input type="hidden" name="user_id" value="{{ user.id }}">
<input type="submit" value="delete" />
</form>
{%endfor%}

Then create a remove_relationship view that does the deletion on the server side, based on the user id you'll now find in request.POST['user_id']



Related Topics



Leave a reply



Submit