24

I want to create a Django model Field (IntegerField) with a default value, and also create a form derived from the model, where the field is optional. If it's not set on the form, then when I save the form, I want the default value saved to the DB.

# model.py
class Invoice(models.Model):
    # IntegrityError "Column 'expireDays' cannot be null"
    expireDays = models.PositiveSmallIntegerField(default=1)

    # expireDays = *null* in DB
    expireDays = models.PositiveSmallIntegerField(default=1, blank=True, null=True)

# forms.py
class InvoiceForm(forms.ModelForm):
    # leaving this line out gives invalid form
    expireDays = forms.IntegerField(required=False)
    class Meta:
        model = Invoice

(I used only one of the field declaration lines at a time. :)

I'm not even sure that I'm declaring the default value correctly. The only reference I could find to it was in an article on handling choices by James Bennett. I have yet to find it in the Django docs (I'm using version 1.2 - maybe it's in 1.3?)

Update - I tried setting the field's default value in the MySql database, to no effect. It seems as if, even when the form does not have a value for the field, it goes ahead and assigns null to the DB, over-riding the MySql default value.

Although I am currently just setting a default value in the view that creates the form - I don't really like that, since it puts the responsibility for the field's integrity in the view, not the DB.

The way I would have thought it would work, is that the field could be set, or not, in the form - if set, that value would be written to the DB, and if not set, the DB default would be used. Instead, if not set, the form is writing a null to the DB. So what's the point of having a default value in the ModelField declaration if it's not used? What exactly does it do?

1 Answer 1

23

i you want field to be optional - just leave second definition in the model and do not add anything in the form definition:

class Invoice(models.Model):
    expireDays = models.PositiveSmallIntegerField(default=1, blank=True, null=True)

class InvoiceForm(forms.ModelForm):
    class Meta:
        model = Invoice

update, so in case there is no value set, use 1 as the field value:

class InvoiceForm(forms.ModelForm):

    def clean_expireDays(self):
        exp_days = self.cleaned_data.get('expireDays')
        if exp_days is None:
            return self.fields['expireDays'].initial
            # above can be: return 1
            # but now it takes value from model definition
        else:
            return exp_days

    class Meta:
        model = Invoice
Sign up to request clarification or add additional context in comments.

2 Comments

My post may not have been clear, but that is one of the combinations I tried - and the MySql data field shows up as null when I do that, not a 1.
Comment on the update - actually, I'm doing it another way - setting the field in the (copied) POST data to a default of 1, before passing the POST data to the form. But that still puts the logic for maintaining data integrity inside the form, and not the database where I want it. The MySql db should be assigning the default value. What I would have expected to happen, is if the form didn't get a value, it wouldn't try to set the DB value - but it seems to be assigning a NULL to the DB, which over-rides even the default value I set by hand in the DB.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.