Joaquin
Joaquin

Reputation: 151

How to query all model objects except the ones that already are in another model?

I am working on a Django application. I have 2 models relevant to the question:

class Quiz(models.Model):
  """
  Represents a Quiz for a `Module`.

  It will have a `name`
  """
  name = models.CharField(max_length=200)
  user = models.ManyToManyField('cme.Bussines', related_name='quizes', through='UserQuiz', through_fields=('quiz', 'user'))

  def __str__(self) -> str:
    return f'{self.name}'

class Trio(models.Model):
  """
  Represents the content for a Module.  

  Each `Trio` will have, as it's name says, 3 content fields, plus the
  `Module` it belongs to.

  It will have a `file`, a `video` (which will be a URL to a YT video), and a `quiz`
  (which will be key to `Quiz`)
  """
  file = models.FileField(upload_to='legacy/classes/', max_length=254)
  quiz = models.ForeignKey(Quiz, on_delete=models.SET_NULL, related_name='trios', null=True, blank=True)
  video = models.URLField()
  module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name='trios')
  user = models.ManyToManyField('cme.Bussines', related_name='trios', through='UserTrio', through_fields=('trio', 'user'))

  def __str__(self) -> str:
    return f'Trio {self.id} de {self.module}'

I want to query all the Quizzes that are not in quiz field of Trio. Is there a way of doing this?

Upvotes: 3

Views: 43

Answers (2)

ticster
ticster

Reputation: 786

You can query all Quiz objects whose id is seen in any Trio object :

Quiz.objects.exclude(id__in=Trio.objects.values("quiz_id"))

You can also refine the query further. For example, let's say you want all Quiz objects not referred by a specific subset of Trio objects, you can do so by adding a filter in your exclude expression, something like :

Quiz.objects.exclude(id__in=Trio.objects.filter(...).values("quiz_id"))

Upvotes: 2

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476967

Yes, you can query with:

Quiz.objects.filter(trios=None)

This will make a LEFT OUTER JOIN and only retain Quizzes for which there is no related Trio object.

Upvotes: 3

Related Questions