Django - 在创建一个实例时触发创建其他实例

时间:2016-02-22 01:04:31

标签: python django

我有三个代表消息,明文和密文的模型:

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时都会自动创建CiphertextMessage实例。实现这一目标的最佳方法是什么?

2 个答案:

答案 0 :(得分: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创建相关模型实例。 1}}对象被保存。

答案 1 :(得分: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)