Aamu
Aamu

Reputation: 3611

Save the user from one model to the another model

What I want to do is, whenever I create a new message, I want the sender of the Message to be added to the user of that particular Thread (the Message its relating to).

How do I do that? Can it be done by overriding the save method? I can do it in the views.py, but I was hoping it would be better if I can add it in the models.py itself. Any help will be very grateful. Thank you!

class Thread(models.Model):
    user = models.ManyToManyField(User)
    is_hidden = models.ManyToManyField(User, related_name='hidden_thread', blank=True)

    def __unicode__(self):
        return unicode(self.id)

class Message(models.Model):
    thread = models.ForeignKey(Thread)
    sent_date = models.DateTimeField(default=datetime.now)
    sender = models.ForeignKey(User)
    body = models.TextField()
    is_hidden = models.ManyToManyField(User, related_name='hidden_message', blank=True)

    def __unicode__(self):
        return "%s - %s" % (unicode(self.thread.id), self.body)

Upvotes: 2

Views: 180

Answers (2)

Peter DeGlopper
Peter DeGlopper

Reputation: 37364

If you don't want to actively pull the user set as dm03514 showed, such as if you want to add users to the thread by default but maintain the ability to remove them from the thread many-to-many later, you can indeed do this by overriding the save method or by using a post_save signal.

save is good enough for almost all cases - the advantage of post_save is that it can more reliably distinguish between saving a new message and saving edits to an existing message. But if you're not creating messages with preselected PKs or loading them from fixtures save can work fine:

class Message(models.Model):
    def save(self, *args, **kwargs):
        probably_new = (self.pk is None)
        super(Message, self).save(*args, **kwargs)
        if probably_new:
            self.thread.user.add(self.sender)

A signal would look like this:

from django.db.models.signals import post_save

def update_thread_users(sender, **kwargs):
    created = kwargs['created']
    raw = kwargs['raw']
    if created and not raw:
        instance = kwargs['instance']
        instance.thread.user.add(instance.sender)

post_save.connect(update_thread_users, sender=Message)

And then review the docs on preventing duplicate signals in case of multiple imports: https://docs.djangoproject.com/en/dev/topics/signals/#preventing-duplicate-signals

Upvotes: 3

dm03514
dm03514

Reputation: 55972

You could lookup the reverse foreign key and get all the users for a particular thread without having to manually put it in Thread

Then you can get users associated with a thread by the reverse lookup:

User.objects.filter(message__thread=thread)

Upvotes: 4

Related Questions