Правильная настройка внешнего ключа on_delete при попытке сохранить исторические данные - PullRequest
0 голосов
/ 19 сентября 2018

У меня быстрый вопрос об использовании ForeignKey в модели.

Допустим, у меня есть модели Car и EngineType.Я хочу, чтобы Car имел EngineType в качестве внешнего ключа для заполнения двигателя автомобиля.Это достаточно просто.

Моя проблема заключается в следующем: допустим, что EngineType должен показывать только активные экземпляры, которые находятся в производстве, поэтому, если они прекратили делать движок 3.5 liter 120 hp из 1970-х, я не будуОн не должен отображаться в списке типов двигателей при создании нового автомобиля.Другая часть этого заключается в том, что я хочу, чтобы все записи оставались в автомобильной базе данных для исторических отчетов.Итак, что происходит, я пытаюсь удалить двигатель, упомянутый выше, и если у меня есть

on_delete=CASCADE

, это не делает то, что я хочу, потому что я теряю исторические данные.Если у меня есть

on_delete=PROTECT

, я не могу удалить ненужную модель двигателя.

Как вы справляетесь с этим?

1 Ответ

0 голосов
/ 19 сентября 2018

Один из вариантов заключается в том, чтобы ваши модели были такими (в основном то, что вы уже предложили):

class EngineType(models.Model):
    ...
    is_active = models.BooleanField(
        default=True)
    ...


class Car(models.Model):
    ...
    engine_type = models.ForeignKey(
        to=EngineType,
        on_delete=models.PROTECT)
    ...

и никогда не удаляйте экземпляры EngineType, которые когда-либо использовались.Старые двигатели должны быть помечены как instance.is_active = False.

Затем в ваших формах и представлениях вам необходимо будет проверить, что только новые активные экземпляры EngineType могут быть назначены новым автомобилям.Есть некоторые вопросы, которые касаются этого, например этот .

Это может выглядеть так (при условии, что вы используете ModelForm):

class CarForm(ModelForm):
    class Meta:
        model = Car
        fields = [
            ...
            'engine_type',
            ...
        ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['engine_type'].queryset = EngineType.objects.filter(is_active=True)

Этот кодбудет гарантировать, что с помощью этой формы этому автомобилю можно будет назначить только активные двигатели.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...