Remove objects with duplicated values from Django queryset

Viewed 210

I want to remove objects with the same field value from a queryset. I've seen some related answers here, but none of them use the annotate and Min feature and I don't know if that approach is even possible.

Imagine I have a 'Book' model with a 'Library' model FK. A Library could have multiple Books with the same title.

How can I obtain a list of Books from that Library with different titles and lower price?

I've tried different approaches with no success:

models.py

class Library(models.Model):
    name = models.CharField(_('Library name'), max_length=255)
    location = models.ForeignKey(Location, on_delete=models.CASCADE)

class Book(models.Model):
    name = models.CharField(_('Title'), max_length=255)
    author = models.CharField(_('Author'), max_length=255)
    editorial = models.CharField(_('Editorial'), max_length=255)
    price = models.FloatField(_('Price'), default=0)
    library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name='libraries',
                                related_query_name='libraries')

Queryset

Book.objects.annotate(count_id=Count('title'), min_price=Min('price')).filter(library__id=21, price=F('min_price')).values_list('title')

Example:

Having this objects | ID | Title | Price | |:---- |:------:| :-----| | 1 | Trainspotting | 3 | | 2 | The Catcher in the rye | 2 | | 3 | Trainspotting | 1 | | 4 | Lord of the Rings | 5 | | 5 | Trainspotting | 5 |

I want to obtain the following queryset:

ID Title Price
2 The Catcher in the rye 2
3 Trainspotting 1
4 Lord of the Rings 5

EDIT:

Using the distinct=True in Count gives me the following results:

In this case my Library contains two Trainspotting books with the same price and two titles of 'The Catcher in the Rye' with prices 2 and 4.

Here I'm printing the annotated fields within the name to see what's could be wrong: Book.objects.annotate(count_id=Count('title', distinct=True), min_price=Min('price')).filter(library__id=21, price=F('min_price')).values_list('name', 'min_price', 'count_id')

The QS I obtain is the following:

<QuerySet [('Trainspotting', 1.0, 1), ('Trainspotting', 1.0, 1), ('The Catcher in the Rye', 2.0, 1), ('The Catcher in the Rye', 4.0, 1)]>

Thanks you very much for your help!

1 Answers
Related