Как создавать таблицы pivot с помощью model_bakery

Я хочу создать рецепт пекаря, который создает один объект, объекты из таблицы pivot и связывает все хорошо.

Инцидент создается, когда ячейки технологии (2g, 3g, 4g, 5g) не работают, но не все технологии затронуты. Поэтому у нас есть сводная таблица для управления этим.

Моя цель - избежать дублирования кода и управлять этим с помощью простого baker.make_recipe("incidents.tests.incident_with_multiple_impacts") для создания инцидента и 4 различных воздействий (технологии создаются в фикстурах)

# incident/models/incident.py
class Incident(models.Model):
    impacted_technologies = models.ManyToManyField(
        Technology, through="IncidentIncidentImpactedTechnologies"
    )

# network/models/technology.py
class Technology(models.Model):
    alias = models.CharField(max_length=2, unique=True, blank=False) # ie: "2G", "3G"...
    name = models.CharField(max_length=4, unique=True, blank=False)

# incident/models/incident_technologies.py
class IncidentIncidentImpactedTechnologies(models.Model):
    incident = models.ForeignKey(
        to="incident.Incident",
        on_delete=models.CASCADE,
        related_name="technology_impacts",
    )
    technology = models.ForeignKey(
        to="network.Technology",
        on_delete=models.CASCADE,
        related_name="impacting_incidents",
    )

В ходе своих исследований я написал код выше (я хочу сохранить первые рецепты, чтобы использовать их в дальнейшем):

from model_bakery.recipe import Recipe, foreign_key, related
 
def get_technology(key=None):
    if key:
        return Technology.objects.get_by_alias(key) # to get it with "2G"
    return random.choice(Technology.objects.all())

incident = Recipe(
    Incident,
    # few other fields
)

impacted_techno = Recipe(
    IncidentIncidentImpactedTechnologies,
    incident=foreign_key(incident),
    technology=get_technology, # Default, take random technology
    # Fields describing a NO_IMPACT on this techno
)

impacted_techno_cell_down = impacted_techno.extend(
    # Fields describing a CELL_DOWN impact on this techno
)

impacted_techno_degraded = impacted_techno.extend(
    # Fields describing a DEGRADED impact on this techno
)

impacted_techno_down = impacted_techno.extend(
    # Fields describing a full TECHNO_DOWN on this techno
)

# Below code is not working, because in incident, impacted_technologies is a O2M field pointing on Technology, not on IncidentIncidentImpactedTechnology.
incident_with_multiple_impacted_technos = incident.extend(
    impacted_technologies=related(
        impacted_techno.extend(technology=lambda: get_technology("2G")),
        impacted_techno_degraded.extend(technology=lambda: get_technology("3G")),
        impacted_techno_down.extend(technology=lambda: get_technology("4G")),
        impacted_techno_cell_down.extend(technology=lambda: get_technology("5G")),
    )
)

Как сделать так, чтобы рецепт создавал все дерево объектов?

Incident # Only one
 |      \
 |        [IncidentIncidentImpactedTechnology] * 4
 |      /    
[Technology] * 4 # already created
Вернуться на верх