Reputation: 2540
I have three models representing a message, plaintext, and ciphertext:
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='')
I would like a Plaintext
and a Ciphertext
instance to be automatically created whenever a Message
is created. What is the best way to accomplish this?
Upvotes: 0
Views: 792
Reputation: 34553
You actually have everything you need just by using a post_save signal:
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)
You don't need or have to override the .save()
method on Message
at all.
Fortunately, post_save
tells us whether or not a new instance was created
or not, allowing you to create the related model instances only when a new object is created, and not every time a Message
object is saved.
Upvotes: 2
Reputation: 7616
By dynamically getting model constructors, you won't have to worry about loading order. You can override the save method or use a post save signal to trigger the create actions.
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
To use a signal -
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)
Upvotes: 0