# Copyright 2010-2011 OpenStack Foundation # Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from django.core import urlresolvers from django.forms import fields from django.forms import widgets class DynamicMultiSelectWidget(widgets.SelectMultiple): """A subclass of the ``Select`` widget which renders extra attributes for use in callbacks to handle dynamic changes to the available choices. """ _data_add_url_attr = "data-add-item-url" def render(self, *args, **kwargs): add_item_url = self.get_add_item_url() if add_item_url is not None: self.attrs[self._data_add_url_attr] = add_item_url return super(DynamicMultiSelectWidget, self).render(*args, **kwargs) def get_add_item_url(self): if callable(self.add_item_link): return self.add_item_link() try: if self.add_item_link_args: return urlresolvers.reverse(self.add_item_link, args=self.add_item_link_args) else: return urlresolvers.reverse(self.add_item_link) except urlresolvers.NoReverseMatch: return self.add_item_link class DynamicMultiChoiceField(fields.MultipleChoiceField): """A subclass of ``ChoiceField`` with additional properties that make dynamically updating its elements easier. Notably, the field declaration takes an extra argument, ``add_item_link`` which may be a string or callable defining the URL that should be used for the "add" link associated with the field. """ widget = DynamicMultiSelectWidget def __init__(self, add_item_link=None, add_item_link_args=None, *args, **kwargs): super(DynamicMultiChoiceField, self).__init__(*args, **kwargs) self.widget.add_item_link = add_item_link self.widget.add_item_link_args = add_item_link_args