binny
binny

Reputation: 729

Duplicate instance returned in QuerySet

I'm attempting to create a method that filters questions based on tags which are only found in a particular user's questions. There is an issue with the QuerySet where it returns Queryset([Question13, Question 14, Question13]). Yet when the .distinct() is added it returns the desired result of QuerySet([Question13, Question 14]).

Why does the second chained .filter() method add the duplicate instance in the QuerySet?

class Post(Model):

    body = TextField()
    date = DateField(default=date.today)
    comment = ForeignKey('Comment', on_delete=CASCADE, null=True)
    profile = ForeignKey(
        'authors.Profile', on_delete=SET_NULL, null=True,
        related_name='%(class)ss',
        related_query_name="%(class)s"
    )
    score = GenericRelation(
        'Vote', related_query_name="%(class)s"
    )


    class Meta:
        abstract = True


class Question(Post):

    title = CharField(max_length=75)
    tags = ManyToManyField(
        'Tag', related_name="questions", related_query_name="question"
    )
    objects = Manager()
    postings = QuestionSearchManager()

class QuestionSearchManager(Manager):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def by_week(self, profile):
        today = date.today()
        weekago = today - timedelta(days=7)
        queryset = self.get_queryset().filter(
            date__range=(weekago, today)
        ).filter(tags__name__in=profile.questions.values_list(
            "tags__name", flat=True
        ))
        return queryset

postings.json

{
    "model": "posts.question",
    "pk": 13,
    "fields": {
        "body": "Content of Question 005",
        "date": "2022-02-12",
        "comment": null,
        "profile": 2,
        "title": "Question__005",
        "tags": [
            1,
            7
        ]
    }
},
{
    "model": "posts.question",
    "pk": 14,
    "fields": {
        "body": "Content of Question 006",
        "date": "2022-02-12",
        "comment": null,
        "profile": 3,
        "title": "Question__006",
        "tags": [
            1,
            2
        ]
    }
}

Upvotes: 0

Views: 60

Answers (1)

Artisan
Artisan

Reputation: 2124

This baffled me for a while also, but it is because of the related tags if the filter references multiple tags and those tags's property name you are now going to return a row per tag reference

distinct is your best friend when filtering using this tags__name style query.

No doubt that because it's a many to many relationship, this will be a common thing you need to be aware of when filtering on that relationship.

This is similar to this question: Logical or of Django many to many queries returns duplicate results

You can also read this section of Django's docs to get a better idea how their queries work: https://docs.djangoproject.com/en/4.0/topics/db/queries/#spanning-multi-valued-relationships

Upvotes: 1

Related Questions