Trouble using union to add QuerySets together

I’m trying to create a listing page of all the questions posted that share the same type of tags a single user has used in their own questions. In other words, if a User has only posted questions about Python and OOP, they would only see questions that shared either one or both of those tags.

Upon trying to implement this, I tried to use the .union() queryset to add the different filtered querysets together. However the following error is raised:

ORDER BY not allowed in subqueries of compound statements.

Is there another means of trying to overcome this error and getting the expected result that doesn’t use the .union() queryset and adding the filtered QuerySets together?

class Question(models.Model):
    title = models.CharField(max_length=50)
    body = models.TextField()
    dated = models.DateField(default=date.today)
    vote_tally = models.IntegerField(default=0)
    user_account = models.ForeignKey(
        'users.UserAccount',
        on_delete=models.SET_NULL,
        null=True, blank=True,
        related_name="questions"
    )
    tags = models.ManyToManyField(Tag, related_name='questions')

    objects = models.Manager()
    dateranges = DateRangeQuerySet.as_manager()
    status = QuestionStatusQuerySet.as_manager()

    class Meta:
        ordering = ['-dated']
        default_manager_name = "objects"

    def __str__(self):
        return self.title
   def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['lookup_buttons'] = {
            'interesting': False,
            'hot': False,
            'week': False,
            'month': False,
        }
        context['all_questions'] = Question.objects.all()
        return context

    def get(self, request):
        context = self.get_context_data()
        lookup = request.GET.get('tab', 'interesting')
        if lookup not in context['lookup_buttons'].keys() or lookup == "interesting":
            user_questions = (
                Question.objects.filter(user_account_id=request.user.id)
                .prefetch_related("tags")
            )
            user_tags = set(
                [tag for question in user_questions
                        for tag in question.tags.all()]
            )
            qs = Question.objects.none()
            tagged_querysets = []
            for tag in user_tags:
                qs = context['all_questions'].filter(tags__name=tag)
                tagged_querysets.append(qs)
                context['all_questions'] = Question.objects.all()
            context['questions'] = qs.union([*tagged_querysets])  # error being raised here

Not that I’ve tried to do this, but I think the issue is that you need to apply the ordering after you’ve done the Union

Also, you’re redefining qs in the for loop, which I don’t think Is going to give you the results you want.

Are you referring to the ordered Meta attribute? So if I need to order a QuerySet in the case get rid of the attribute and use the .order_by() method?

Hi Ben,

I think you can avoid the union if you traverse the relationships correctly. From what I’m reading you want to fetch the questions which have tags shared with questions that are assigned to the current user. If that’s correct, here’s what I would suggest:

...

if lookup not in context['lookup_buttons'].keys() or lookup == "interesting":
    related_questions = Question.objects.filter(
        tags__question__user_account_id=request.user.id,
    )
    all_questions = Question.objects.all()
    context.update({"questions": related_questions, "all_questions": all_questions})

...
1 Like

I want to get all questions submitted by all users that share similar tags.

  • Me – Only posted questions that are tagged Python and OOP

  • Other Users - Posted questions that are tagged Java, JavaScript, Python, Networking, OOP

I want to see not only my questions about Python and OOP, but I also only want to see the other user questions that are tagged Python and/or OOP. I cannot test it out now, but is that what you have in your example?

Yes, it should be.

(filler text for the forum’s minimum post length)

I applied this and ended up getting the following error:
FieldError at / Related Field got invalid lookup: question

https://docs.djangoproject.com/en/3.2/topics/db/queries/#spanning-multi-valued-relationships

Looking at this again. My tags field refers to a Tag model which only has one attribute, name.
So I believe that’s why the FieldError is being raised.

So am I going to have change my Tag model with a FK to Question?

You don’t have your Tag model posted here - seeing that will help.

Also, try “questions” instead of “question”. (That’s what you have in the related_name argument.)

Also, try “questions” instead of “question”. (That’s what you have in the related_name argument.)

I did as you suggested by using questions and now it works.

Sorry about that! I didn’t review your code carefully enough.