Implemented ArrayFieldSelectMultiple form widget

This commit is contained in:
Jeremy Stretch 2017-02-16 13:15:17 -05:00
parent ac2bf91a87
commit 5c8c0e543f
2 changed files with 42 additions and 3 deletions

View File

@ -1,6 +1,7 @@
import re import re
from django import forms from django import forms
from django.contrib.postgres.forms.array import SimpleArrayField
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db.models import Count, Q from django.db.models import Count, Q
@ -8,9 +9,9 @@ from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFi
from ipam.models import IPAddress from ipam.models import IPAddress
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
APISelect, add_blank_choice, BootstrapMixin, BulkEditForm, BulkImportForm, CommentField, CSVDataField, APISelect, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, BulkImportForm, CommentField,
ExpandableNameField, FilterChoiceField, FlexibleModelChoiceField, Livesearch, SelectWithDisabled, SmallTextarea, CSVDataField, ExpandableNameField, FilterChoiceField, FlexibleModelChoiceField, Livesearch, SelectWithDisabled,
SlugField, SmallTextarea, SlugField,
) )
from .formfields import MACAddressFormField from .formfields import MACAddressFormField
@ -248,11 +249,28 @@ class RackFilterForm(BootstrapMixin, CustomFieldFilterForm):
# #
class RackReservationForm(BootstrapMixin, forms.ModelForm): class RackReservationForm(BootstrapMixin, forms.ModelForm):
units = SimpleArrayField(forms.IntegerField(), widget=ArrayFieldSelectMultiple(attrs={'size': 10}))
class Meta: class Meta:
model = RackReservation model = RackReservation
fields = ['units', 'description'] fields = ['units', 'description']
def __init__(self, *args, **kwargs):
super(RackReservationForm, self).__init__(*args, **kwargs)
# Populate rack unit choices
self.fields['units'].widget.choices = self._get_unit_choices()
def _get_unit_choices(self):
rack = self.instance.rack
reserved_units = []
for resv in rack.reservations.exclude(pk=self.instance.pk):
for u in resv.units:
reserved_units.append(u)
unit_choices = [(u, {'label': str(u), 'disabled': u in reserved_units}) for u in rack.units]
return unit_choices
# #
# Manufacturers # Manufacturers

View File

@ -169,6 +169,27 @@ class SelectWithDisabled(forms.Select):
force_text(option_label)) force_text(option_label))
class ArrayFieldSelectMultiple(SelectWithDisabled, forms.SelectMultiple):
"""
MultiSelect widgets for a SimpleArrayField. Choices must be populated on the widget.
"""
def __init__(self, *args, **kwargs):
self.delimiter = kwargs.pop('delimiter', ',')
super(ArrayFieldSelectMultiple, self).__init__(*args, **kwargs)
def render_options(self, selected_choices):
# Split the delimited string of values into a list
if selected_choices:
selected_choices = selected_choices.split(self.delimiter)
return super(ArrayFieldSelectMultiple, self).render_options(selected_choices)
def value_from_datadict(self, data, files, name):
# Condense the list of selected choices into a delimited string
data = super(ArrayFieldSelectMultiple, self).value_from_datadict(data, files, name)
return self.delimiter.join(data)
class APISelect(SelectWithDisabled): class APISelect(SelectWithDisabled):
""" """
A select widget populated via an API call A select widget populated via an API call