2016-02-22 7 views
0

У меня есть три модели, представляющее сообщение, открытый текст и зашифрованный текст:Джанго - Срабатывание создания других случаев, когда один экземпляр создается

class Message(models.Model): 
    key = models.ForeignKey(Key, on_delete=models.CASCADE, related_name='messages') 
    created = models.DateTimeField(auto_now_add=True) 
    title = models.CharField(max_length=50, blank=True, default='') 
    owner = models.ForeignKey(User, related_name='messages') 

class Plaintext(models.Model): 
    message = models.OneToOneField(
     Message, 
     on_delete=models.CASCADE, 
     primary_key=True 
    ) 
    text = models.TextField(blank=True, default='') 


class Ciphertext(models.Model): 
    message = models.OneToOneField(
     Message, 
     on_delete=models.CASCADE, 
     primary_key=True 
    ) 
    text = models.TextField(blank=True, default='') 

Я хотел бы Plaintext и Ciphertext экземпляра будут созданы автоматически всякий раз, когда Message. Каков наилучший способ сделать это?

+0

Я пробовал переопределить 'save' на' Message'. Мне было интересно, есть ли стандартный способ сделать это. –

+0

Вы хотите взглянуть на: https://docs.djangoproject.com/en/1.9/topics/signals/ – Brandon

ответ

2

Вы на самом деле есть все, что нужно только с помощью post_save сигнал:

from .models import Plaintext, Ciphertext 


def create_plain_and_cipher_text(sender, instance, created, **kwargs): 
    if created: 
     Plaintext.objects.create(message=instance) 
     Ciphertext.objects.create(message=instance) 

Вам не нужно или нужно переопределить .save() метод на Message на всех.

К счастью, post_save говорит нам о том, или не новый экземпляр был created или нет, что позволяет создать соответствующие экземпляры модели только тогда, когда создается новый объект, а не каждый раз, когда Message объект сохраняется.

+0

Я хотел бы прояснить то, что не сразу видно из документации: если я использую декоратор '@ receiver', мне не нужно называть' Signal.connect', правильно? –

+0

Исправить. Вам просто нужно убедиться, что ваш сигнальный код зарегистрирован. – Brandon

0

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

from django.apps import apps 

class Message(models.Model): 
    ... 
    def save(self,*args,**kwargs): 
     PLAIN_TEXT_MODEL = apps.get_model(app_label='your_app_name_here', model_name='Plaintext') 
     CIPHER_TEXT_MODEL = apps.get_model(app_label='your_app_name_here', model_name='Ciphertext') 
     new_pt_model = PLAIN_TEXT_MODEL.objects.create(some_field=self.some_field_in_message_model,some_other_field = 1) 
     CIPHER_TEXT_MODEL.objects.create(some_field="Something") 
     super(Message,self).save(*args,**kwargs) # call default save method 

Чтобы использовать сигнал -

from django.db.models import signals 

class Message(models.Model): 
    ... 

def your_callable_function(sender, instance, **kwargs): 
    # do something, create other model instances, etc 

signals.post_save.connect(your_callable_function, sender=Message) 
+0

Модели зарегистрированы в ['ModelBase .__ new__()'] (https: // github. ком/Джанго/Джанго/BLOB/6670da75ff8a59b2ec0b465846e3f76aab9155b2/Джанго/дб/модели/base.py # L283). Если вы импортируете модель напрямую, вам не нужно беспокоиться о порядке загрузки, так как загрузка модели в реестр является побочным эффектом ее импорта. Нет причин использовать 'apps.get_model()', если вам не нужно динамически выбирать разные классы моделей. – knbk

+0

Если эти модели находятся в одной и той же 'models.py' и определены в порядке, указанном в OP, тогда будет вызван' NameError'. –

+0

Правильно, это единственный файл. По-прежнему не нужно использовать 'apps.get_model()', все определения классов выполняются до того, как метод '.save()' когда-либо вызывается. Трудно проверить, что использование моделей в методе фактически не приведет к 'NameError', даже если сам метод определен перед классом, который он ссылается. – knbk

Смежные вопросы