Как получить объект с внешним ключом в системе many-to-many

У меня есть отношения "многие-ко-многим".

class Module(BaseModel):
    name = models.TextField(unique=True, null=False)
    groups = models.ManyToManyField(ModuleGroup, db_table='module_group_members')

class ModuleGroup(BaseModel):
    name = models.TextField(unique=True, null=False)

Я хочу получить список модулей и связанных с ними групп, примерно так:

{[
  {
  'name' : 'name1'
  'groups' : ['group1', 'group2']
  },
 'name' : 'name2'
  'groups' : ['group6', 'group7']
  }
]}

Попробовал так:

modules = Module.objects.filter(is_active=True)
print('values_list', list(modules.values('name', 'groups')))

Что дает e:

[{'name': 'name1', 'groups__name': 'group2'}, {'name': 'name1', 'groups__name': 'group2'}, {'name': 'name2', 'groups__name': 'group6'}, {'name': 'name2', 'groups__name': 'group7'}, ]

Есть ли способ сгруппировать одинаковые модули так, чтобы имена групп находились в списке?

from collections import defaultdict

modules = Module.objects.filter(is_active=True)

# We'll need an intermediary for data transformation
# defaultdict is a good choice because then there's no worry about instantiating new list objects for each new key that is encountered
modules_dict = defaultdict(list)

# Add each group to the list of whatever name it belongs to
for module in modules:
    modules_dict[module['name']].append(module['groups__name'])

# modules_dict will by now look something like:

'''
{
    name1: [group1, group2]
}
'''

# So now it's just a matter of formatting the data structure to your liking
print([{'name': name, 'groups': groups} for name, groups in modules_dict.items()])

прежде всего

вам нужно создать модель, предполагая, что у вас есть эти две модели с полем is_active в классе Module okay

from django.db import models
from django.db.models import Prefetch


class ModuleGroup(models.Model):
    name = models.TextField(unique=True, null=False)

class Module(models.Model):
    name = models.TextField(unique=True, null=False)
    groups = models.ManyToManyField(ModuleGroup, db_table='module_group_members')
    is_active = models.BooleanField(default=True)  # Assuming you have this field in your model

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

from yourapp.models import Module, ModuleGroup  


# Create some ModuleGroup instances
group1 = ModuleGroup.objects.create(name='group1')
group2 = ModuleGroup.objects.create(name='group2')
group3 = ModuleGroup.objects.create(name='group6')
group4 = ModuleGroup.objects.create(name='group7')

# Create some Module instances and associate them with ModuleGroup instances
module1 = Module.objects.create(name='name1', is_active=True)
module1.groups.add(group1, group2)

module2 = Module.objects.create(name='name2', is_active=True)
module2.groups.add(group3, group4)

после этого сделайте этот фильтр

# Fetch the modules and prefetch related groups
modules = Module.objects.filter(is_active=True).prefetch_related(
    Prefetch('groups', queryset=ModuleGroup.objects.only('name'))
)

# Prepare the desired output format
result = []
for module in modules:
    groups = [group.name for group in module.groups.all()]
    result.append({
        'name': module.name,
        'groups': groups
    })

если вы напечатаете список

print(result)

вы должны получить

[{'name': 'name1', 'groups': ['group1', 'group2']}, {'name': 'name2', 'groups': []}]
Вернуться на верх