Last active
April 21, 2016 14:30
-
-
Save cwurld/f77e69598451404f30bacc46005a0a75 to your computer and use it in GitHub Desktop.
django and select2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
I have a model for customer intake. One of the fields is for tracking how the customer heard about us. I do | |
not want an endless proliferation of values, so I would like to use a multi-select. The problem is I also want the | |
user to add new choices as needed. It turns out this is possible with the Select2 widget: | |
https://select2.github.io/examples.html#tokenizer - check out this link to see how to setup your javascript. | |
It turns out this is a little tricky to implement. Below is a mixin you can use with a form to handle the field. | |
Also, if you are using bootstrap, you will want: https://fk.github.io/select2-bootstrap-css/ | |
''' | |
class Intake(TimeStampedModel): | |
referral = models.CharField(max_length=1000, blank=True) # save as json encoded list | |
@classmethod | |
def get_referral_choices(cls): | |
""" | |
:return: a set of referal choices | |
""" | |
cut_off = datetime.datetime.now() - datetime.timedelta(200) | |
all_db_values = cls.objects.filter(created__gt=cut_off).values_list('referral', flat=True) | |
choice_set = {'Google', 'Bing'} | |
for v in all_db_values: | |
if v: | |
choices = json.loads(v) | |
choice_set.update(choices) | |
return choice_set | |
class ReferralFieldMixin(object): | |
def __init__(self, *args, **kwargs): | |
super(ReferralFieldMixin, self).__init__(*args, **kwargs) | |
self.fields['referral'].widget.attrs.update({'class': 'select2-tokenizer'}) | |
self.fields['referral'].help_text = 'To create a new choice, type it followed by a space.' | |
referral_choices_set = set(models.Intake.get_referral_choices()) | |
if self.initial and self.initial.get('referral'): | |
self.initial['referral'] = json.loads(self.initial['referral']) | |
referral_choices_set.update(self.initial['referral']) | |
if 'data' in kwargs and kwargs['data'].get('referral'): | |
# kwargs['data'] needs to be converted to a normal dict to get the referral field as a list | |
referral_choices_set.update(dict(kwargs['data'])['referral']) | |
referral_choices = sorted(list(referral_choices_set)) | |
self.fields['referral'].choices = [[x, x] for x in referral_choices] | |
def clean_referral(self): | |
referral = map(methodcaller('capitalize'), self.cleaned_data['referral']) | |
return json.dumps(referral) | |
class IntakeForm(ReferralFieldMixin, forms.ModelForm): | |
referral = forms.MultipleChoiceField(required=False) | |
class Meta: | |
model = models.Intake | |
fields = ['referral'] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment