Hide a field from a django modelform
Asked Answered
D

2

6

The django documentation suggests I can identify hidden / visible fields from within my template. I have two models, AddressInfo and PharmacyInfo. I need to enter data for both tables from a single page. I want to hide the address_id field (from the PharmacyInfo model). I currently have:

    {% for form in formset %}
    {% if form.non_field_errors %}
        <div class="form_errors">
            {{ form.non_field_errors }}
        </div>
    {% endif %}

    {% for field in form.visible_fields%}
        <div class="field_content">                  
                <label>{{field.label_tag }}</label>
        <div class="field">

            {% if field.help_text %}
            <div class = "help_text">
                {{ field.help_text }}
            </div>
            {% endif %}               
                {{ field }}
                {{ field.errors }}
        </div> 
        </div>
    {% endfor %}
{% endfor %}



class PharmForm(ModelForm):
    class Meta:
        model = PharmInfo
        widgets = {
            'address_id': forms.HiddenInput()
        }



class AddressForm(ModelForm):
    class Meta:
        model = AddressInfo



class AddressInfo(models.Model):
    address_id = models.AutoField(primary_key=True)

    address_1 = models.CharField("Address Line 1", max_length = 64)
    address_2 = models.CharField("Address Line 2", max_length = 64, blank=True, null=True)
    address_3 = models.CharField("Address Line 3", max_length = 64, blank=True, null=True)
    address_4 = models.CharField("Address Line 4", max_length = 64, blank=True, null=True)
    town_city = models.CharField("Town or City", max_length = 32)
    post_code = models.CharField("Post Code", max_length = 8)
    phone = models.CharField("Phone Number - numbers 0-9 only", 
                        max_length = 16) #this must be numeric 0-9 only for auto-dial functionality.
    email = models.CharField("email address", max_length = 64) #must be valid email



class PharmInfo(models.Model):
    pharm_id = models.AutoField(primary_key=True)
    pharm_name = models.CharField("Pharamcy Name", max_length = 64)
    address_id = models.ForeignKey(AddressInfo, db_column="address_id")



def pharmView (request, id=None):
    pharmForm = PharmForm()
    addForm = AddressForm()
    if request.method == 'POST': #this is a form submission
        if id == None: #it's a new record
            pharmForm = PharmForm(request.POST)
            addForm = AddressForm(request.POST)
            if addForm.is_valid(): #add the address_id into the pharmForm.
                request.POST = request.POST.copy()
                request.POST['address_id'] = addForm.save().pk
                pharmForm = PharmForm(request.POST)
                if pharmForm.is_valid(): 
                    pharm = pharmForm.save()
                    return render_to_response('thanks.html', 
                        {'form1': pharmForm,
                         'form2': addForm},
                        context_instance=RequestContext(request),
                    )

        else: #it's an existing record
            pharm = PharmInfo.objects.get(pk=id)
            address = pharm.address_id
            pharmForm = PharmForm(request.POST, instance = pharm)
            addForm = AddressForm(request.POST, instance = address)
            if pharmForm.is_valid() and addForm.is_valid():
                pharmForm.save()
                addForm.save()
                return render_to_response('updateThanks.html',
                    {'form1': pharmForm,
                     'form2': addForm},
                    context_instance=RequestContext(request),
                )
    else: 
        if id != None: #form bound to a pharmacy record
            pharm = PharmInfo.objects.get(pk=id)
            address = pharm.address_id
            pharmForm = PharmForm(instance = pharm)
            addForm = AddressForm(instance = address)
            return render_to_response('institutions/pharm.html', 
                {'form1': pharmForm,
                 'form2': addForm},
                context_instance=RequestContext(request),
                )            

    return render_to_response('institutions/pharm.html', 
            {'form1': pharmForm,
             'form2': addForm},
            context_instance = RequestContext(request),
        )

This code hides the input box for the address_id field but the label is still shown. I want to hide the whole div but 'form.visible_fields' isn't excluding it from the output. This is driving me nuts. Can anyone tell me how to mark the address_id field in a way visible to the template.

Distilled answered 13/6, 2011 at 12:42 Comment(2)
Long time ago I had similar problems. I ended up creating a subclass of forms.Form that specified what fields should be displayed separately, so very much abandoning Django's capacity to generate such form for you. The advantage was that I was still using Django's standard components for the form but could leave the unnecessary fields out, but it was a rather ugly solution. Can give you an example if you want though.Kerbing
Can you show how address_id field is defined in the PharmInfo model?Carmen
D
2

OK, looks like I was editing the wrong code in my template. I'd added

{% for field in form.visible_fields %}

to a part of the template that I'd commented out (I find commented lines difficult to see on templates). Everything works as expected with the code below in my template:

{% if form.non_field_errors %}
        <div class="form_errors">
            {{ form.non_field_errors }}
        </div>
    {% endif %}

    {% for field in form.visible_fields %}
    <div class="field_content">
        <label>{{ field.label_tag }}</label>  
    <div class="field">

        {% if field.help_text %}
        <div class = "help_text">
            {{ field.help_text }}
        </div>
        {% endif %}

        {{ field }}
        {{ field.errors }}
    </div> 
    </div>
    {% endfor %}

Apologies to anyone who spent time on this (I would have posted early but being new to Stackoverflow I wasn't allowed to answer my own question within 8 hours of posting).

Distilled answered 14/6, 2011 at 7:49 Comment(0)
O
21

If you don't intend on the address_id field to be edited at all in the form, you should use the exclude meta field as documented in Using a subset of fields in the form.

The result should look like:

class PharmForm(ModelForm):
    class Meta:
        model = PharmInfo
        exclude = ('address_id',)

Note that this will prevent the address_id field from being set through the form (check the note under the example in the docs).

Orthodontist answered 13/6, 2011 at 16:8 Comment(1)
I needed the PharmForm.address_id to be included on the form. It's created when the AddressForm saves - rather than entered by the user.Distilled
D
2

OK, looks like I was editing the wrong code in my template. I'd added

{% for field in form.visible_fields %}

to a part of the template that I'd commented out (I find commented lines difficult to see on templates). Everything works as expected with the code below in my template:

{% if form.non_field_errors %}
        <div class="form_errors">
            {{ form.non_field_errors }}
        </div>
    {% endif %}

    {% for field in form.visible_fields %}
    <div class="field_content">
        <label>{{ field.label_tag }}</label>  
    <div class="field">

        {% if field.help_text %}
        <div class = "help_text">
            {{ field.help_text }}
        </div>
        {% endif %}

        {{ field }}
        {{ field.errors }}
    </div> 
    </div>
    {% endfor %}

Apologies to anyone who spent time on this (I would have posted early but being new to Stackoverflow I wasn't allowed to answer my own question within 8 hours of posting).

Distilled answered 14/6, 2011 at 7:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.