intargc
intargc

Reputation: 3111

Massage model data before save in Django

I'm not sure if this is the best way to do this, but I have some data that is being sent by a form. I have a ModelForm that takes the the request.POST of that form data. All the data that is being sent is a description, amount and deposit (boolean).

When the person submits the data, the amount will be a positive number, but I would like to store it in the database as a negative number if deposit is False.

I was thinking of doing this in either the Model or the ModelForm and sort of massage that amount before saving... So, somewhere in one of those classes, I'd like to have something like:

if not deposit:
    amount = -amount

... and then save it as such.

Is there a way to handle this in the ModelForm or Model that would keep me from having to do all that logic inside of the view?

Upvotes: 1

Views: 2245

Answers (2)

dani herrera
dani herrera

Reputation: 51665

Overwrite model save method is a solution. But I prefear make this operations in clean method and mix it with business rules:

models.py:

from django.db import models 
class Issue(models.Model):
    ....
    def clean(self): 
        rules.Issue_clean(self)

from issues import rules
rules.connect()

rules.py:

from issues.models import Issue
def connect():

    from django.db.models.signals import post_save, pre_save, pre_delete
    #issues 
    pre_delete.connect(Issue_pre_delete, sender= Incidencia) 
    pre_save.connect(Issue_pre_save, sender = Incidencia ) 
    post_save.connect(Issue_post_save, sender = Incidencia )

def Incidencia_clean( instance ): 
    #pre save:
    if not instance.deposit:
        instance.amount *= -1 

    #business rules:
    errors = {}

    #dia i hora sempre informats     
    if not instance.account.enoughCredit: 
        errors.append( 'No enough money.' )

    if len( errors ) > 0: 
        raise ValidationError(errors) 

def Issue_pre_save(sender, instance, **kwargs): 
    instance.clean()

At this way rules are binded to model and you don't need to write code on each form that this model appears (here, you can see this on more detail)

Upvotes: 2

catavaran
catavaran

Reputation: 45575

ModelForm's save() method is a good place for this:

class MyForm(models.ModelForm):
    ...
    def save(self):
        instance = super(MyForm, self).save(commit=False)
        if not self.deposit:
            self.amount = -self.amount
        instance.save()
        return instance

Upvotes: 4

Related Questions