ManyToManyField в моделях Django - PullRequest
       23

ManyToManyField в моделях Django

0 голосов
/ 05 декабря 2018

Мне нужно создать набор таких моделей:

class Step(models.Model):
    field1 = models.CharField(max_length=50)
    field2 = models.CharField(max_length=50)

class Scenario(models.Model):
    name = models.CharField(max_length=50)
    steps = models.ManyToManyField(Step, related_name="scenarios")

Дело в том, что я хочу, чтобы сценарий включал несколько шагов в порядке, который я буду указывать, и даже один и тот же шаг несколько раз.Например:

Scenario1:
    step1
    step2
    step1
    step3

Я хочу, чтобы порядок этого шага был легко редактируемым на сайте администратора.Я узнал о filter_horizontal, это похоже на то, что мне нужно на сайте администратора, но у него нет возможности добавить шаг еще раз и перемещать шаги вверх и вниз.

1 Ответ

0 голосов
/ 05 декабря 2018

В компьютерной науке есть поговорка, которая гласит: « Все проблемы в компьютерной науке могут быть решены с помощью другого уровня косвенности » - Дэвид Уилер.

В этом случае вы должны использовать "сквозную" таблицу, например:

class Step(models.Model):
    field1 = models.CharField(max_length=50)
    field2 = models.CharField(max_length=50)

class Scenario(models.Model):
    name = models.CharField(max_length=50)
    steps = models.ManyToManyField(
        Step,
        <b>through='ScenarioStep'</b>,
        related_name="scenarios"
    )

class ScenarioStep(models.Model):
    scenario = models.ForeignKey(
        'Scenario',
        on_delete=models.CASCADE,
        related_name='scenariostep'
    )
    step = models.ForeignKey(
        'Step'
        on_delete=models.CASCADE,
        related_name='scenariostep'
    )
    order = models.PositiveIntegerField()

    class Meta:
        ordering = ['order']

Здесь мы, таким образом, вводим дополнительную модель, которая заменяет скрытую "сквозную таблицу", которая уже была создана ManyToManyField.

A Scenario, таким образом, имеет Step, учитывая, что есть запись ScenarioStep, и мы упорядочиваем ее по полю Order.

Мы можем, например, добавитьданные шаги к scenario с:

s1 = Step.objects.create(field1='step1')
s2 = Step.objects.create(field1='step1')
s3 = Step.objects.create(field1='step1')

sc1 = Scenario.objects.create(name='Scenario1')

ScenarioStep.objects.create(order=1, scenario=sc1, step=s1)
ScenarioStep.objects.create(order=2, scenario=sc1, step=s2)
ScenarioStep.objects.create(order=3, scenario=sc1, step=s1)
ScenarioStep.objects.create(order=4, scenario=sc1, step=s3)

Затем мы можем перебрать шаги с:

for step in sc1.steps.order_by('scenariostep'):
    # ... (do something with the step)
    pass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...