Дубликаты экземпляров не удаляются из набора запросов

Я столкнулся с проблемой, связанной с набором запросов, возвращаемых в методе get_tag_posts внутри модели Profile. При использовании запроса в том виде, в котором он написан, он не удаляет дубликаты, даже если вызывается метод .distinct().

Краткая иллюстрация проблемы:

  • Вопрос 1 - тег A
  • Вопрос 2 - Метка A
  • Вопрос 3 - тег A, тег B

Когда вызывается get_tag_posts, он включает следующий набор запросов: <QuerySet [<Tag: A>, <Tag: A>, <Tag: A>, <Tag: B>]>

Однако я ожидаю, что набор запросов будет возвращен в виде: <QuerySet [<Tag: A>, <Tag: B>]>

После этого каждый экземпляр аннотируется, чтобы подсчитать, сколько раз данный тег был размещен пользователем. Почему в этом случае не удаляются дубликаты одного экземпляра?

class Profile(Model):
    user = OneToOneField(settings.AUTH_USER_MODEL, on_delete=CASCADE)

    def get_tag_posts(self, order_by=None):
        if not order_by:
            order_by = "-question__date"
        elif order_by == "name":
            pass
        else:
            order_by = "-score"

        questions_with_tag = Subquery(self.questions.filter(
            tags__name=OuterRef("name")).only('id'))
        tags = Tag.objects.filter(
            question__profile=self
        ).distinct().order_by(order_by)
        return {
            'records': tags.annotate(times_posted=Count(questions_with_tag)),
            'title': f"{tags.count()} Tags"
        }
class Tag(Model):    

    name = CharField(unique=True, max_length=25)



class Post(Model):

    body = TextField()
    date = DateTimeField(default=timezone.now)
    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"
    )
    vote = GenericRelation(
        'Vote', related_query_name="%(class)s"
    )
    score = IntegerField(default=0)


class Question(Post):

    title = CharField(
        max_length=80, unique_for_date="date",
        help_text="Concisely state the problem you're having",
        error_messages={
            "max_length": "The title of your question is too long"
        }
    )
    tags = ManyToManyField(
        'Tag', related_name="questions", related_query_name="question"
    )
    views = IntegerField(default=0)
    visible = BooleanField(default=True)
    objects = Manager()
    postings = QuestionSearchManager()
    searches = QueryStringSearchManager()

Отношения "многие ко многим" на самом деле включают 3 таблицы. В вашем примере: Вопросы, Теги, Question_Tag_Relations

Question_Tag_Relations

PK Question_PK Tag_PK
1 1 1
2 2 1
3 3 1
4 3 2

Когда вы захватываете distinct(), вы захватываете Distinct PKs в этой таблице отношений, а не сами теги.

Поэтому вам нужно получить tag_pk (не знаю конкретного названия столбца)
. Некоторые БД поддерживают разделение по столбцам, например: ~.distinct('tag_pk')
Но если ваша БД этого не поддерживает, то вам, возможно, придется сделать так: ~.values_list('tags').distinct()... Я считаю, что это дополнительный запрос

Это было бы моим предположением: Tags.objects.filter(pk__in=self.questions.values_list('tags').distinct())

Вернуться на верх