Package: django-collectionfield
A reusable Django model field to store collections.Featureshighly configurablemodel field(changing collection and item types, sorting, choices, item uniqueness and more)custom lookupsto simplify queries over collection itemsform fieldsfor working with collectionscollectionitem validatorsextendedget_FIELD_displaymethod for model fields with choicesworks with database backends without native support for multi-value columns (like ArrayField for PostgreSQL)Installationpipinstalldjango-collectionfieldUsageModel fieldDefine model with field that stores lists of strings:# models.pyfromdjango.dbimportmodelsfromcollectionfield.modelsimportCollectionFieldclassMyModel(models.Model):tags=CollectionField()Pass values to model field:my_model=MyModel.objects.create(tags=['test','values'])my_model.values['test','values']Making queriesRetrieve model instances with particular value present in the collection:MyModel.objects.filter(tags__has='test')Retrieve model instances withALLvalues present in the collection (ignoring items’ order):MyModel.objects.filter(tags__hasall=['test','values'])Retrieve model instances withANYof values present in the collection:MyModel.objects.filter(tags__hasany=['test','values'])Customizing collectionsCustom collection and item type:classIntegerSet(models.Model):# This field will provide sets of integers# instead of default lists of strings:values=CollectionField(collection_type=set,item_type=int)Sorting and uniqueness:classSortedUniqueTextList(models.Model):# Before saving, items will be sorted and duplicates dropped:texts=CollectionField(sort=True,unique_items=True)Choices and collection size limit:classTaggedModel(models.Model):tags=CollectionField(# Both choices and max_items limit are checked during model validation.choices=(('action',"Action"),('comedy',"Comedy"),('horror',"Horror"),# ...),max_items=2)get_FIELD_displaymethod can handle multiple choices and provide options to customize the display:tagged_model=TaggedModel.objects.create(tags=['action','horror'])tagged_model.get_tags_display()"Action, Horror"defli_mapper(value,label):return"<li>{0}</li>".format(label)deful_wrapper(field_display):return"<ul>{0}</ul>".format(field_display)tagged_model.get_tags_display(delimiter='',mapper=li_mapper,wrapper=ul_wrapper)'<ul><li>Action</li><li>Horror</li></ul>'Django built-in validators work with entire field values.django-collectionfieldprovide validation of single collection items:fromcollectionfield.validatorsimport(ItemMinValueValidator,ItemMaxValueValidator)classIntegerList(models.Model):values=CollectionField(item_type=int,# item validators check each item separately:validators=[ItemMinValueValidator(1),ItemMaxValueValidator(5)])Form fieldsdjango-collectionfieldcomes with 2 form fields:fromcollectionfield.formsimportCollectionField,CollectionChoiceField# ``collectionfield.forms.CollectionField`` converts comma-separated text# into collection of values:classMyForm(forms.Form):values=CollectionField()my_form=MyForm({'values':"A, B, C"})my_form.is_valid()Truemy_form.cleaned_data['values']['A','B','C']# ``collectionfield.forms.CollectionChoiceField`` behaves more like# regular MultipleChoiceField:classMyChoiceForm(forms.Form):values=CollectionChoiceField(choices=(('action',"Action"),('comedy',"Comedy"),('horror',"Horror"),# ...))my_choice_form=MyChoiceForm({'values':['action','comedy']})my_choice_form.is_valid()Truemy_choice_form.cleaned_data['values']['action','comedy']Both form fields support the same set of parameters as the model field:fromcollectionfield.formsimportCollectionFieldclassMyForm(forms.Form):values=CollectionField(collection_type=set,item_type=int)my_form=MyForm({'values':"1, 2, 1, 3"})my_form.is_valid()Truemy_form.cleaned_data['values']{1,2,3}Representation in databaseCollectionField converts its values into string of up to 1024 characters using the following format:"|item1|item2|item3|"Default delimiter (‘|’) and maximum length can be configured:classMyModel(models.Model):values=CollectionField(delimiter="$",max_length=2000)RequirementsPython: 2.7, 3.4, 3.5Django: 1.8, 1.9, 1.10