Как создавать таблицы 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