Подтвердить что ты не робот

Может ли Django автоматически создавать связанную модель "один-к-одному"?

У меня две модели в разных приложениях: modelA и modelB. У них есть отношения "один к одному". Есть ли способ, которым django может автоматически создавать и сохранять ModelB при сохранении modelA?

class ModelA(models.Model):
    name = models.CharField(max_length=30)

class ModelB(models.Model):
    thing = models.OneToOneField(ModelA, primary_key=True)
    num_widgets = IntegerField(default=0)

Когда я сохраняю новый ModelA, я хочу, чтобы запись автоматически сохранялась в ModelB. Как я могу это сделать? Есть ли способ указать это в ModelA? Или это невозможно, и мне просто нужно создать и сохранить ModelB в представлении?

Отредактировано, что модели находятся в разных приложениях.

4b9b3361

Ответ 1

Взгляните на AutoOneToOneField в django-annoying. Из документов:

from annoying.fields import AutoOneToOneField

class MyProfile(models.Model):
    user = AutoOneToOneField(User, primary_key=True)
    home_page = models.URLField(max_length=255)
    icq = models.CharField(max_length=255)

(django-annoying - это небольшая библиотека, которая включает в себя такие драгоценные камни, как декоратор render_to и функции get_object_or_None и get_config)

Ответ 2

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

Используя сигналы:

В ваших models.py:

from django.db.models import signals


def create_model_b(sender, instance, created, **kwargs):
    """Create ModelB for every new ModelA."""
    if created:
        ModelB.objects.create(thing=instance)

signals.post_save.connect(create_model_b, sender=ModelA, weak=False,
                          dispatch_uid='models.create_model_b')

Вы можете создать отдельное приложение для хранения этого файла models.py, если оба приложения находятся в готовом виде.

Ответ 3

Самый простой способ - переопределить метод сохранения ModelA:

class ModelA(models.Model):
    name = models.CharField(max_length=30)

    def save(self, force_insert=False, force_update=False):
        is_new = self.id is None
        super(ModelA, self).save(force_insert, force_update)
        if is_new:
            ModelB.objects.create(thing=self)

Ответ 4

Я думаю, вы хотите использовать наследование модели django. Это полезно, если вы выполняете следующее утверждение: ModelA - это ModelB (например, "Ресторан - это местоположение" ).

Вы можете определить:

class ModelB(models.Model):
    field1 = models.CharField(...)

class ModelA(ModelB): field2 = models.CharField(...)

Теперь вы можете создать экземпляр ModelA и задать поле2 и поле1. Если эта модель будет сохранена, она также создаст экземпляр ModelB, который получит значение field1. Все это делается прозрачно за кулисами.

Хотя вы можете сделать следующее:

a1 = ModelA()
a1.field1 = "foo"
a1.field2 = "bar"
a1.save()
a2 = ModelA.objects.get(id=a1.id)
a2.field1 == "foo" # is True
a2.field2 == "bar" # is True
b1 = ModelB.objects.get(id=a1.id)
b1.field1 == "foo" # is True
# b1.field2 is not defined

Ответ 5

Я знаю это немного позже, но я придумал более чистое и элегантное решение. Рассмотрим этот код:

class ModelA(models.Model):
    name = models.CharField(max_length=30)

    @classmethod
    def get_new(cls):
        return cls.objects.create().id



class ModelB(models.Model):
    thing = models.OneToOneField(ModelA, primary_key=True, default=ModelA.get_new)
    num_widgets = IntegerField(default=0)

Конечно, вы можете использовать лямбда, если вы возвращаете целочисленный идентификатор связанного объекта:)

Ответ 6

Вы можете использовать post_save-hook, который запускается после сохранения записи. Дополнительную документацию по сигналам django см. Здесь здесь. На на этой странице вы найдете пример того, как применить крючок к вашей модели.

Ответ 7

Просто создайте функцию, которая создает и возвращает пустой ModelA, и задает по умолчанию аргумент по умолчанию для "вещи".