1243916142
1243916142

Reputation: 385

How to rewrite the Django model save method?

How to rewrite the Django model save method?

class Message(models.Model):
    """
    message
    """
    message_num = models.CharField(default=getMessageNum, max_length=16)  

    title = models.CharField(max_length=64)
    content = models.CharField(max_length=1024)

    def save(self, force_insert=False, force_update=False, using=None,
         update_fields=None):
        # I want send email there
        pass

I mean, in the Django model, if I create instance success, I want to call a function, such as send a email in the function.

I find in the Django model have a save method. I am not sure whether should write other code, because there are so many params.

I mean whether I only should care about my send email logic?

Upvotes: 0

Views: 3225

Answers (3)

Sijan Bhandari
Sijan Bhandari

Reputation: 3061

You need to activate signal once your message is saved. That means, when your message is saved, django will issue signal as follows:

from django.db.models.signals import post_save
from django.dispatch import receiver

class Message(models.Model):
    # fields...

# method for sending email
@receiver(post_save, sender=Message, dispatch_uid="send_email")
def send_email(sender, instance, **kwargs):
    # your email send logic here..

You can put your signals in signals.py file inside your app folder and make sure to import that in your application config file as follows:

message/apps.py

from django.apps import AppConfig

class MyAppConfig(AppConfig):
    name = 'message'

    def ready(self):
        import message.signals

And update init file as follows:

message/__init__.py

default_app_config = 'message.apps.MyAppConfig'

Upvotes: 2

user2390182
user2390182

Reputation: 73498

When you override the save method, you still have to make sure that the it actually saves the instance. You can do that by simply calling the parent class' save via super:

class Message(models.Model): 
    # ...
    def save(self, *args, **kwargs):
        # this will take care of the saving
        super(Message, self).save(*args, **kwargs)
        # do email stuff  
        # better handle ecxeptions well or the saving might be rolled back

You can also connect the mail sending to the post_save (or pre_save, depending on your logic) signal. Whether you want to separate one orm the other in that way depends on how closely the two actions are linked and a bit on your taste.

Overriding save gives you the option to intervene in the saving process, e.g. you can change the value of fields based on whether the mail sending was successful or not save the instance at all.

Upvotes: 6

Marcus Lind
Marcus Lind

Reputation: 11470

The solution to what you want to do is to use Django Signals. By using Signals you can hook code to when a model is created and saved without having to rewrite the save method, that keep the separation of code and logic in a much nicer way, obviously the model does not need to know about the emails for example.

An example of how to use Signals would be to simply do the following:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel

@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):
    # Code to execute whenever MyModel is saved...

If you still want to override the save() method you can use the Python super() method to do so (docs).

class MyModel(models.Model):
    def save(self, *args, **kwargs):
        # This will call the parent method that you are overriding
        # so it will save your instance with the default behavior.
        super(MyModel, self).save(*args, **kwargs)

        # Then we add whatever extra code we want, e.g. send email...
        Messenger.send_email()

Upvotes: 4

Related Questions