2

I am new to django and I think it is fantastic so far. I faced this weird issue today: I have this FormModel:

class RegisterForm2(UserCreationForm):
    mobile2 = forms.CharField(
        label=_('Mobile Confirmation'),
        max_length=50,
        required=True,
        widget = forms.TextInput(attrs = {'class':'nocopy'})
    )

    class Meta:
        model = User
        fields = ['username', 'mobile', 'mobile2', 'guardian_mobile']
        labels = {
            'username': _('Government ID'),
        }
        widgets = {
            # workaround since __init__ setting to required doesnt work
            'mobile': forms.TextInput(attrs = {'required':''}),
        }

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

        self.fields['mobile'].required = True

Now mobile field has blank=True in the model but i want it to be required in the form only and so I did that in the __init__ . Now it is making the field required but it is not adding required="" to the text input. Now if i have overridden the field (and added the required=True) like I did mobile2 field I wouldn't have this issue. This is a an issue because if i want the attribute required to show on fields i have to override the fields in the form to add the required=True which will go against the DRY principle. Am I missing something or is this a bug of some sort?

Edit: I failed to mention that I am using floppy forms. It could be related to that. I have to investigate this issue further.

John-Silver
  • 35
  • 1
  • 7
  • 1
    Possible duplicate of [differentiate null=True, blank=True in django](http://stackoverflow.com/questions/8609192/differentiate-null-true-blank-true-in-django) – Sayse May 05 '16 at 07:41
  • That is exactly what `blank` is used for – Sayse May 05 '16 at 07:41
  • @Sayse I wanted to leave model field as blank=True but enforce required=True from the modelform without overriding the definition for the whole field. I was able to do that from the __init__ but the field shows without the "required" HTML attribute. – John-Silver May 05 '16 at 09:01
  • Oh so you're looking for client side validation rather than the server side? Alasdairs answer covers that – Sayse May 05 '16 at 09:04

3 Answers3

2

Note this answer assumes you are using regular Django forms, I wrote it before you mentioned that you were using floppy forms.

Django does not currently add the required HTML 5 attribute when it renders form fields. Overriding the widget for the mobile field sounds looks OK to me. You are changing the widget, not duplicating the field, so I don't think you need to worry about it being DRY.

Note that setting required in the __init__ is having an effect - if you submit the form with an empty value for mobile, then you will get a validation error. Your mobile2 field will not have required in the rendered HTML unless you add it to its widget attrs.

Django will add the required attribute to form fields in Django 1.10, see ticket #22383.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • i am using django 1.95 and in it adds required attribute in HTML for mobile2 although i didnt add it in the widget attrs. django will add the attribute required only if u redefine the field again in the form (not DRY) and specify required=True. – John-Silver May 05 '16 at 08:58
  • *it adds the required attribute in HTML for mobile2* -- That's not the behaviour I see in Django 1.9, or expect by looking at the code/ticket. Maybe you are rendering the fields in some custom way that you haven't told us about (e.g. using crispy forms). – Alasdair May 05 '16 at 09:10
  • could it be related to floppy forms? I failed to mention that – John-Silver May 05 '16 at 09:41
  • If you're using floppy-forms them you'll see different behaviour. [It does include the required attribute](http://django-floppyforms.readthedocs.io/en/latest/differences.html#required-attribute). – Alasdair May 05 '16 at 09:48
1

This is actuially possible in your __init__. You just have to add the required attribute to the widget attributes:

def __init__(self, *args, **kwargs): super(RegisterForm2, self).__init__(*args, **kwargs) self.fields['mobile'].required = True self.fields['mobile'].widget.attrs['required'] = 'required'

nortchuck
  • 621
  • 5
  • 2
0

but i want it to be required in the form only

'mobile': forms.TextInput(attrs = {'required':''}),

You can do this in views.py also. That's how I prefer to do it.

form.fields['mobile'].widget.attrs['required'] = True