Проблема 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")
Полезные ссылки:
- https://docs.djangoproject.com/en/3.2/ref/models/querysets/#django.db.models.query.QuerySet.values_list
- https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ManyToManyField.related_name .
- https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ManyToManyField.through .