Nesting html/css inside widget.attrs, i.e. a button with a button icon inside the button attrs

I’ve got a drop down menu which I’ve changed the css on by adding a class to the widget attrs like this:

forms.py:

class BoxModelForm(forms.ModelForm):

	BOX_SIZE=[
			('small', 'Small Box'),
			('medium', 'Medium Box'),
			('large', 'Large Box'),
			]
		
	box_size_needed = forms.CharField(widget=forms.Select(choices=BOX_SIZE))
		
	class Meta:
		model = Box
		fields = (
			'box_size_needed',
		)

	def __init__(self, *args, **kwargs):
		super(ProductModelForm, self).__init__(*args, **kwargs)
		self.fields['box_size_needed'].widget.attrs.update({'class': 'button','aria-haspopup=': 'true', 'aria-controls': 'dropdown-menu'})

Normally with buttons not part of forms, if I want an icon in the button I add the button like this:

<button class="button">
	<span>Drop Down</span>
	<span class="icon is-small">
		<i class="fas fa-angle-down" aria-hidden="true"></i>
	</span>
</button>

With this form I’m adding the button with {{ form.box_size_needed }} :

<p class="title">Box Size</p>
<div class="dropdown is-active">
	{{ form.box_size_needed }}
</div>

I’m not sure how to add an icon inside the button with the little down arrow so it looks like a drop down instead of a regular button:

<span class="icon is-small">
	<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>

The example implementation of a drop down button using Bulma the css framework I’m using is:

<div class="dropdown is-active">
  <div class="dropdown-trigger">
    <button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
      <span>Dropdown button</span>
      <span class="icon is-small">
        <i class="fas fa-angle-down" aria-hidden="true"></i>
      </span>
    </button>
  </div>
  <div class="dropdown-menu" id="dropdown-menu" role="menu">
    <div class="dropdown-content">
      <a href="#" class="dropdown-item">
        Dropdown item
      </a>
      <a class="dropdown-item">
        Other dropdown item
      </a>
      <a href="#" class="dropdown-item is-active">
        Active dropdown item
      </a>
      <a href="#" class="dropdown-item">
        Other dropdown item
      </a>
      <hr class="dropdown-divider">
      <a href="#" class="dropdown-item">
        With a divider
      </a>
    </div>
  </div>
</div>

My drop down is all working nicely and styled how I want, it’s saving the selection to the model, the only thing is just getting the little drop down arrow inside it, I’m not sure how to get the icon in there. Know how I can nest the icon code inside the button when it’s used in a form?

Also the reason why I’m applying the css to the individual field element is that the form is much longer with other fields including a file upload field. I had to style the upload field using attrs as well since I’m already using Bulma CSS and I couldn’t find a nice Bulma package like crispy forms that has the file upload element correctly implemented. So I had to individually style the upload field as well as the other elements in this form. I just shortened the form for this example using one drop down. Thanks

Class Select in django.forms.widgets shows that the template_name being rendered is ‘django/forms/widgets/select.html’.

You could either:

  • Subclass Select and change that attribute to refer to a template with the html you want rendered, then use that class as your widget.

  • Create your own template and put it in that directory within your app’s templates directory so that when the form is rendered it picks up your template instead of the system’s template. (See How to override templates | Django documentation | Django)