24

I am making a profile form in Django. There are a lot of optional extra profile fields but I would only like to show two at a time. How do I hide or remove the fields I do not want to show dynamically?

Here is what I have so far:

class UserProfileForm(forms.ModelForm):
    extra_fields = ('field1', 'field2', 'field3')
    extra_field_total = 2

    class Meta:
        model = UserProfile

    def __init__(self, *args, **kwargs):
        extra_field_count = 0
        for key, field in self.base_fields.iteritems():
            if key in self.extra_fields:
                if extra_field_count < self.extra_field_total:
                    extra_field_count += 1
                else:
                    # do something here to hide or remove field
        super(UserProfileForm, self).__init__(*args, **kwargs)
1

4 Answers 4

28

I think I found my answer.

First I tried:

field.widget = field.hidden_widget

which didn't work.

The correct way happens to be:

field.widget = field.hidden_widget()
Sign up to request clarification or add additional context in comments.

4 Comments

what if you have an invalid value in the hidden field? you users will go nuts...
@benzkji this is often used with select/radio inputs, naturally
I can see that this might be often used, and will work in some, maybe even many cases. But if your field is a choice field, and you have old, invalid values in your database, those records cannot be saved anymore, because the hidden widget will contain an invalid value.
Instead of field.hidden_widget() you can also put forms.HiddenInput()
5
def __init__(self, *args, **kwargs):
    is_video = kwargs.pop('is_video')
    is_image = kwargs.pop('is_image')
    super(ContestForm, self).__init__(*args, **kwargs)
    if is_video:
        del self.fields['video_link']
        # self.exclude('video_link')
    if is_image:
        del self.fields['image']

use delete instead of self.exclude().

1 Comment

Why del is better than self.exclude()?
4

Can also use

def __init__(self, instance, *args, **kwargs):    
    super(FormClass, self).__init__(instance=instance, *args, **kwargs)
    if instance and instance.item:
        del self.fields['field_for_item']

Comments

1

You are coding this in the Form. Wouldn't it make more sense to do this using CSS and JavaScript in the template code? Hiding a field is as easy as setting "display='none'" and toggling it back to 'block', say, if you need to display it.

Maybe some context on what the requirement is would clarify this.

4 Comments

Firstly, just because I think form logic should stay in the form. Also, because I see what fields have already been filled out before and don't show those.
This moves business logic into the presentation layer ("these objects don't have this field"). Especially bad if the web developer is NOT the backend developer.
what if a value in a hidden field is not valid (any more)? you'll get "please correct the errors below"...happy searching.
this can be achieved with something like if (mainField.value === 'value') { dependentField.style.display = 'block';

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.