Escher
Escher

Reputation: 5795

How to exclude django form field from render but still keep it for validation?

If I have a model (extract):

class Coupon(models.Model):
    image = models.ImageField(max_length=64, null=True, upload_to="couponimages")

And a form (extract):

class InsertCoupon(forms.ModelForm):
    image=forms.ImageField(
        required=False, #note explicitly declared false
        max_length=64,
        widget=forms.FileInput() 
        )
    class Meta:
        model=Coupon,
        exclude = ("image",)

Then I notice that the image field is still rendered when I do {{ form.as_table }}. If I remove the explicit declaration of the field from the form class, then it doesn't render, but I don't get the benefit of form validation and easy modelform insertion to the database. I want to use my own widget for this field (FileInput is ugly) - do I have to hence code all the html myself, or is there a way to use as_table?

Upvotes: 7

Views: 6436

Answers (4)

Hubert Dryja
Hubert Dryja

Reputation: 81

I think the best way to achieve that is to create a widget that renders nothing:

class NoInput(forms.Widget):
    input_type = "hidden"
    template_name = ""

    def render(self, name, value, attrs=None, renderer=None):
        return ""

class YourForm(forms.Form):
    control = forms.CharField(required=False, widget=NoInput)

This way you can still use {{form}} in your template.

Upvotes: 7

tklodd
tklodd

Reputation: 1079

The best way to do what you want to do here is write a custom widget to display the file field differently. However, the best way to answer the exact question you asked, without having to render the form manually in the templates, is to overwrite the as_table method of the form:

class InsertCoupon(forms.ModelForm):

    def as_table(self, *args, **kwargs):
        del self.fields['image']
        return super(InsertCoupon, self).as_table(*args, **kwargs)

Upvotes: 5

Escher
Escher

Reputation: 5795

So a better way to exclude just a single field in the template might be:

<table>
{% for field in form %}
    {% if field != "image" %}
    <tr><td>{{ field }}</td></tr>
    {% endif %}
{% endfor %}
</table>

Beats manually writing out all the fields.

Upvotes: 6

Hasan Ramezani
Hasan Ramezani

Reputation: 5194

You can render form manualy like this:

in views.py

return render(request, 'template.html', {'form': form})

in template.html

<form action="/your-name/" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.field1 }}
    {{ form.field2 }}
          .
          .
          .
    <input type="submit" value="Submit" />
</form>

also take a look to Working with forms.

Upvotes: 0

Related Questions