Search code examples
djangodjango-modelsdjango-querysetdjango-annotate

Django Annotate - get list of distinct field values


I have 3 models - Book, Page and Language.

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)

class Page(models.Model):
    image = models.ImageField(upload_to='Uploaded_images')
    language = models.ForiegnKey(Language, models.CASCADE)
    book = models.ForeignKey(Book, models.CASCADE)

class Language(models.Model):
    name = models.CharField(max_length=20)

There's a one-to-many relationship between Book and Page objects. Some pages in a book can be of a different language, so I added the ForeignKey in Page model and not in the Book model.

I want to get the list of all books along with the languages its pages were written in.

I tried this:

books = Page.objects.annotate(
        name=F('book__title')
    ).values(
        'name', 'book_id'
    ).distinct(
    ).annotate(
        page_count=Count('id'),
    ).values(
        'name', 'book_id', 'language'
    )

If there are 2 languages in the book, I get 2 entries for the same book title. I just need 1 entry for the book and be able to show its languages as a list.

Ex: If there's a book with pages in either of the 2 languages, Spanish and English, I'd like to extract the book title and the languages in it as ['English', 'Spanish'].

Is this doable?


Solution

  • If you use Postgres, maybe you need start get data from class Book and use ArrayAgg.

    Link: Django queryset annotate field to be a list/queryset

    If you use rest-framework, you can use Serializer.