Проблема Manytomanyfields : Получение столбцов, к которым применяется поле manytomanyfield

(Извините за неуместное название. Я очень плохо знаю английский. Поэтому я не смог найти, как должно быть название)

У меня есть 2 таблицы Devices и groups

class Devices(models.Model):
    id = models.AutoField(primary_key=True)
    device_name =\
        models.CharField(max_length=100, null=False)

class Groups(models.Model):
    group_id = models.AutoField(primary_key=True)
    devices = models.ManyToManyField(Devices, blank=True)

У меня более 100000 устройств и 100 групп. Устройства могут иметь несколько групп. Я хочу получить идентификаторы групп для каждого устройства. Я пытался перебрать все устройства и получить столбец группы. Но это занимает слишком много времени. Есть ли какой-нибудь питонический способ решить эту проблему?

В ManyToManyField создается одна промежуточная модель для сохранения отношения. Вы можете легко получить доступ к этой модели и отфильтровать соответствующие данные.

Эта модель имеет три поля:

  • Автонумеровое поле id.
  • Другое поле id для модели, которая имеет ManyToManyField. Его название <<Name of the model in lower case>>_id: groups_id now.
  • Другое поле id, указывающее на модель в ManyToManyField. Соглашение об именах такое же. devices_id в данном случае.

Теперь, имея доступ к связанной модели, вы можете запрашивать ее как обычную модель Django.


class Devices(models.Model):
    id = models.AutoField(primary_key=True)
    device_name = models.CharField(max_length=100, null=False)

    def get_group_ids(self):
        return Groups.get_ids_by_device(self)

class Groups(models.Model):
    group_id = models.AutoField(primary_key=True)
    devices = models.ManyToManyField(Devices, blank=True)

    @classmethod
    def get_ids_by_device(cls, device):
        relation = cls.devices.through
        qs = relation.objects\
            .filter(devices_id=device.pk)\
            .values_list('groups_id', flat=True)
        return list(qs)

Для упрощения кода вы можете легко получить доступ к промежуточной модели через атрибут related_name.

class Devices(models.Model):
    id = models.AutoField(primary_key=True)
    device_name = models.CharField(max_length=100, null=False)

    def get_group_ids(self):
        relation = self.groups.through
        qs = relation.objects\
            .filter(devices_id=self.pk)\
            .values_list('groups_id', flat=True)
        return list(qs)

class Groups(models.Model):
    group_id = models.AutoField(primary_key=True)
    devices = models.ManyToManyField(Devices, blank=True, related_name="groups")

Полезные ссылки:

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