开发者

Rewriting Django template {% for %} into a Model method

开发者 https://www.devze.com 2023-02-26 08:56 出处:网络
I have existing code that works: {% for author in seminar.authors.all %} {{ author.first_name}} {{ author.last_name }}

I have existing code that works:

{% for author in seminar.authors.all %}
{{ author.first_name}} {{ author.last_name }}
{% if forloop.l开发者_Python百科ast %}{% else %}, {% endif %}
{% endfor %}

As you may have guessed, seminar.authors is a m2m field. Generic, nothing special.

I know how to write Model methods, but im not sure how to properly loop through each author item per seminar object and apply a comma if the current iteration is all but last.

Would it be alright to name this Model method get_author_display? Im not sure if this clashes with Django's built-in get_*_display.

furthermore, I'd love to support a few forloop.last conditions:

  • 1 author name = no comma or "and"
  • 2 author names = comma
  • 3 or more author names = commas w/ "and" prepending the last author name.

but in an elegant manner. Ideas?


Are you sure your second extra requirement is correct? Surely with just two names you want "and" and no comma?

Anyway, there's nothing particularly difficult about this. The trick is to get the queryset's length first - note that it's actually more efficient to use len rather than .count() here, because count() on an unevaluated queryset does a separate call to the database.

def get_author_display(self):
    authors = self.authors.all()
    length = len(authors)
    output = []
    for i, author in enumerate(authors):
        val = "%s %s" % (author.first_name, author.last_name)
        if i == (length-1) and length > 2:
             val = "and " + val
        output.append(val)
    return ', '.join(output)

And no, there's nothing wrong with calling the method that: authors will never have CHOICES set, so won't get an automatic get_foo_display method.

0

精彩评论

暂无评论...
验证码 换一张
取 消