2

I have a Django form which has an ImageField in it, and I render the field like this in my template:

{{ form.my_image_field }}

The resulting HTML looks like this:

Currently: <a href="https://....s3.amazonaws.com/....jpg">....jpg</a>
<input name="my_image_field-clear" id="my_image_field-clear_id" type="checkbox">
<label for="my_image_field-clear_id">Clear</label><br>
Change:
<input name="my_image_field" id="id_my_image_field" type="file">

I want to render only the <input element, since I am using the bootstra-fileinput library: https://www.npmjs.com/package/bootstrap-fileinput :

<input name="my_image_field" id="id_my_image_field" type="file">

Is it possible to do this without writing the <input> tag manually in the template?

sytech
  • 29,298
  • 3
  • 45
  • 86
Babken Vardanyan
  • 14,090
  • 13
  • 68
  • 87
  • why don't you add just `` in template? not using django form – seuling Jun 24 '18 at 07:16
  • @seuling It's not flexible. Why write more code? For example what if tomorrow I need to change the name of the field? Or standardize all my widgets? – Babken Vardanyan Jun 24 '18 at 07:20
  • Few ways to go about this. Do you want this behavior only for `ImageField`s or for any/all input fields? Do you need the HTML elements actually gone, or would it be acceptable if the extra HTML elements were just visually/textually hidden? – sytech Jun 24 '18 at 07:33
  • @BabkenVardanyan you're right. But if you use `{{ form.my_image_field }}`, didn't you get only `input` field? – seuling Jun 24 '18 at 07:53
  • @sytech I want this behaviour only for `ImageFields`. It is acceptable if elements are just hidden, but that should include the `Currently:` and `Change:` texts as well. – Babken Vardanyan Jun 24 '18 at 08:00
  • @seuling No, please see the first part of the question. – Babken Vardanyan Jun 24 '18 at 08:00

2 Answers2

7

Normally, ImageFields use the ClearableFileInput widget. This widget by default uses the template name django/forms/widgets/clearable_file_input.html.

You can make your own ClearableFileInput widget subclass that uses a different template.

from django.forms.widgets import ClearableFileInput

class MyImageWidget(ClearableFileInput):
    template_name = "myapp/my_template.html"

The content of that template may just be simply the <input> part of the default template with the extraneous label and checkbox removed. You can customize it however you need. That might look like

<!-- myapp/my_template.html -->
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>

Then in your form specify the widget for the ImageField

class MyForm(forms.Form):
    #  ...
    my_image_field = forms.ImageField(widget=MyImageWidget)
    #  ...

Django also provides a FileInput widget which uses a plain template. If that suits your needs simply do

class MyForm(forms.Form):
    #  ...
    my_image_field = forms.ImageField(widget=forms.widgets.FileInput)

Alternatively, you could simply override the default template by creating the django/forms/widgets/clearable_file_input.html file in your project's template directory. However, this would apply the change to the rendering of all fields using the ClearableFileInput widget, so it is not as flexible of an approach.

sytech
  • 29,298
  • 3
  • 45
  • 86
  • 1
    Good answer, and there is already such a widget in Django called `FileInput` which uses a template with plain `` tag, adjust your answer and I'll accept it. – Babken Vardanyan Jun 24 '18 at 07:59
0

you can use the form.name and form.id_for_label template variables to dynamically set the name and id attributes of the input field for the ImageField based on the form's name and id

Here is an example for your project:

<input type="file" name="{{my_image_field.name}}" id="{{my_image_field.id_for_label}}">

Hope it will be helpful for orthers!

baolq
  • 1