Search code examples
pythondjangoformsrequiredsubclass

How to make a subclassed, custom Django form field non-required?


The Django docs (http://docs.djangoproject.com/en/dev/ref/forms/fields/) say that you can create a subclass of django.forms.Field as long as it implements a clean() method and its init() method accepts the core arguments (required, label, initial, widget, help_text).

I was trying to use the code in the following Django Snippet: http://djangosnippets.org/snippets/907/ to implement a credit card field, but I want it to be non-required. Setting required=false works just fine for normal fields, but not for the subclassed fields in this snippet. What is the snippet missing? (I think it's init() method is missing or not accepting the core arguments mentioned in the Django docs, but I'm not sure how to fix this.)

For example, setting required to false on these custom fields, the form still requires them:

CC_number = CreditCardField(required=False)
CC_expiration_date = CCExpField(required=False)

The form doesn't require this field (it works as expected):

CC_security_code = forms.IntegerField(required=False)

Thanks for your help!


Solution

  • This should work, by modifying the clean method in CreditCardField (first 2 lines of method):

    def clean(self, value):
        if not value and not self.required:
            return value
        """Check if given CC number is valid and one of the
           card types we accept"""
        if value and (len(value) < 13 or len(value) > 16):
            raise forms.ValidationError("Please enter in a valid "+\
                    "credit card number.")
        elif self.get_cc_type(value) not in ("Visa", "MasterCard",
                                                 "American Express"):
            raise forms.ValidationError("Please enter in a Visa, "+\
                "Master Card, or American Express credit card number.")
        return super(CreditCardField, self).clean(value)