How to DRY (myself) in Django form for Create and Edit Form

240 views Asked by At

I created two forms in Django for the same model, named AccountCreateForm and AccountEditForm. The Account model has say three fields and each of them has a few form attributes such as max_length, help_text, error_messages. For example,

class AccountCreateForm(forms.Modelform):
    name = forms.CharField(max_length=50, required=True, label='Account Name', help_text='50 characters max', error_messages={'required': 'Please enter the account name'})
    number = forms.CharField(max_length=16, required=True, label='Phone Number', help_text='10-16 digits max', error_messages={'required': 'Please enter the phone numbername'})

I want the user to be able to edit the existing accounts as well. So, I added another form for editing purposes as follow.

class AccountEditForm(forms.Modelform):
    name_error = { 'max_length': ("Name should be no longer than 50 characters."), 'required': ("Please enter the account name")}
    number_error = {'max_length': ("Phone number should be between 10-16 characters."),'min_length': ("Phone number should be between 10-16 characters."),'required': ("Please enter the phone number tied to the Twilio account")}

    name = forms.CharField(max_length=50, required=True, label='Account Name', help_text='50 characters max', error_messages=name_error)
    number = forms.CharField(max_length=16, required=True, label='Phone Number', help_text='10-16 digits max', error_messages=number_error)

And my template for both account_create.html and account_edit.html share simple code like this:

    <form method="post">
        {% csrf_token %}
        <p>
        {% for field in form %}
            {{ field.errors }}
            <label for="{{ field.id_for_label }}">{{ field.label }}({{ field.help_text }}):</label>
            <br />
            {{ field }}<br /><br />
        {% endfor %}
        </p>
        <input class="btn btn-primary done-btn" type="submit" value="Create New Account">
    </form>

It works fine and Django helps provide error messages and help texts fine. But, I feel like I'm repeating things here. I tried the approach suggested by Django documentation page like this:

class AccountEditForm(forms.Modelform):
    class Meta:
        model = Account
        fields = ('name', 'number')
        labels = {'name' : _('Account Name'), 'number': _('Phone Number')}
        error_messages = {
                'name': {
                    'max_length': _("Name should be no longer than 50 characters."), 'required': ....}

and so on. But then if I intentionally left, say the name field, blank in edit form, Django doesn't show error. The only way it'll show error seems the first approach. Is there something that I can do to improve the code quality (that is, to be not repetitive)? Thank you.

1

There are 1 answers

3
mukesh On BEST ANSWER

There can be two ways to accomplish this:-

1) Make the name field required inside the model by adding 'blank=False'.

    name = models.CharField(blank=False)

2) If you don't want to modify blank setting for your fields inside models (doing so will break normal validation in admin site), you can do the following in your Form class:

def __init__(self, *args, **kwargs):
    super(AccountEditForm, self).__init__(*args, **kwargs)

    self.fields["name"].required = True