Search code examples
djangomodels

Querying manytomany field using a list of objects in django returning multiple rows with same id


Say that I have a manytomany field, and say that I have x amount of elements.

class Distinct_Alert(models.Model):
    alert_type = models.ForeignKey(Alert_Type, on_delete=models.CASCADE)
    entities = models.ManyToManyField(to='Entity', through='Entity_To_Alert_Map')
    objects = Utility_Manager()

class Entity(models.Model):
    label = models.CharField(max_length=255, blank=False)
    entity_type = models.ForeignKey(Entity_Type_Label)
    related_entities = models.ManyToManyField('self')
    identical_entities = models.ManyToManyField('self')
    objects = Entity_Manager()

    class Meta:
        unique_together = ('label', 'entity_type')

I am currently doing something

Distinct_Alert.objects.filter(alert_type=alert_type, entities__in=[entity[0] for entity in entities]).all()

but for some reasons, this query returns 2 distinct alerts with the same id, any idea why? If I add distinct() to it that solves the issue, but I'm trying to use get since the table should technically only have one entry matching that query.

I was initially doing this:

Distinct_Alert.objects.get_or_none(alert_type=alert_type, entities__in=[entity1, entity2....])

but then this bounced with an error, get_or_none is defined like so

class Utility_Manager(models.Manager):
    def get_or_none(self, **kwargs):
        try:
            return self.get(**kwargs)
        except self.model.DoesNotExist:
            return None

but this won't work since I have 2 elements that are being returned, it would be an odd case if the elements were different and matching on the same query, but the rows that are returned are literally the same row.


Solution

  • When queries span multiple rows, duplicates should be expected.

    From the docs:

    By default, a QuerySet will not eliminate duplicate rows. In practice, this is rarely a problem, because simple queries such as Blog.objects.all() don’t introduce the possibility of duplicate result rows. However, if your query spans multiple tables, it’s possible to get duplicate results when a QuerySet is evaluated. That’s when you’d use distinct()

    So like you've done, using distinct is the standard way for eliminating dups.