Rewriting Django template {% for %} into a Model method
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.
精彩评论