Access Model Method for Multiple Objects in Django

Question:

Let’s say I have created a model in Django that looks like this:

class Book(models.Model):
    author = models.CharField(max_length=64)
    ... (other attributes)

    def author_pretty(self):
        return "[··" + self.author +  "··]"

I need to get from all objects in DB the method author_pretty, as of now I’m doing this:

authors = Book.objects.values_list('author', flat=True)
authors_pretty = ["[·" + author +  "·]" for author in authors]
# or
books = Book.objects.all()
authors_pretty = [book.author_pretty() for book in books]

Is there any way of doing this in a single call? Django would still have to make a query to DB and the call the method, but maybe there is a cleaner solution that I’m missing.

Asked By: Stack

||

Answers:

It depends on how you are going to use it, if it is one by one on a template, use the method as a property

@property
def author_pretty(self):
        return "[··" + self.author +  "··]"

However if you want something cleaner and for some reason you need them all in once, take a look into Django Docs for Concat, Query Expressions and Annotate

from django.db.models.functions import Concat
from django.db.models import Value, CharField

Book.objects.all().annotate(author_pretty=Concat(Value(“[··”), “author”, Value(“··]”), output_field=CharField()))

And then you can use it in a for loop like a property

for author in authors:
    print(author.author_pretty)
Answered By: Alejandro Franco