Ripped this out of a project I'm working on. The field renders as two <select> elements representing the two-level hierarchy organized events Facebook uses. Returns the id's Facebook wants.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | from django.utils.translation import ugettext as _
from django.forms import MultiValueField
from django.forms.widgets import Widget, Select
from django.utils.safestring import mark_safe
from django.utils import simplejson
"""
var categorySelect = function(el, target, tree){
var list = tree[el.getValue()];
target.setTextValue('');
for (var key = 0; key < list.length; key++){
var option = document.createElement('option');
option.setValue(list[key][0]);
option.setTextValue(list[key][1]);
target.appendChild(option);
}
};
"""
class CategorySelect(Widget):
category_name = '%s_category'
def __init__(self, choice_tree, attrs=None):
self.attrs = attrs or {}
category_choices = []
choices_map = {}
for cat_id, cat_label, subcats in choice_tree:
category_choices += ((cat_id, cat_label),)
choices_map[cat_id] = subcats
self.category_choices = category_choices
self.choices_map = choices_map
def value_from_datadict(self, data, files, name):
cat_value = data.get(self.category_name % name, '')
subcat_value = data.get(name, '')
return cat_value, subcat_value
def render(self, name, value, attrs={}):
# Value is id of the bottom choice.
category_value = None
choices = ()
if value:
for cat_id, subcats in self.choices_map.items():
for subcat_id, subcat_label in subcats:
if str(subcat_id) == str(value):
category_value = str(cat_id)
choices = subcats
break
else:
category_value = self.category_choices[0][1]
choices = self.choices_map.values()[0]
output = []
category_id = 'id_%s_category' % name
category_attrs = {
'id': category_id,
'onchange': 'categorySelect(this, document.getElementById(\'id_%s\'), %s);' % \
(name, simplejson.dumps(self.choices_map))
}
output.append(Select().render(self.category_name % name, category_value, category_attrs, self.category_choices))
output.append(Select().render(name, value, attrs, choices))
return mark_safe(u'\n'.join(output))
class CategoryField(MultiValueField):
FACEBOOK_EVENT_SUBCATEGORIES = [
_('Birthday Party'),
_('Cocktail Party'),
_('Club Party'),
_('Potluck'),
_('Fraternity/Sorority Party'),
_('Business Meeting'),
_('Barbecue'),
_('Card Night'),
_('Dinner Party'),
_('Holiday Party'),
_('Night of Mayhem'),
_('Movie/TV Night'),
_('Drinking Games'),
_('Bar Night'),
_('LAN Party'),
_('Brunch'),
_('Mixer'),
_('Slumber Party'),
_('Erotic Party'),
_('Benefit'),
_('Goodbye Party'),
_('House Party'),
_('Reunion'),
_('Fundraiser'),
_('Protest'),
_('Rally'),
_('Class'),
_('Lecture'),
_('Office Hours'),
_('Workshop'),
_('Club/Group Meeting'),
_('Convention'),
_('Dorm/House Meeting'),
_('Informational Meeting'),
_('Audition'),
_('Exhibit'),
_('Jam Session'),
_('Listening Party'),
_('Opening'),
_('Performance'),
_('Preview'),
_('Recital'),
_('Rehearsal'),
_('Pep Rally'),
_('Pick-Up'),
_('Sporting Event'),
_('Sports Practice'),
_('Tournament'),
_('Camping Trip'),
_('Daytrip'),
_('Group Trip'),
_('Roadtrip'),
_('Carnival'),
_('Ceremony'),
_('Festival'),
_('Flea Market'),
_('Retail')]
FACEBOOK_EVENTS = (
(_('Party'), (0,23)),
(_('Causes'), (23,27)),
(_('Education'), (27,31)),
(_('Meetings'), (31,36)),
(_('Music/Arts'), (36,45)),
(_('Sports'), (45,48)),
(_('Trips'), (48,53)),
(_('Other'), (53,-1))
)
def __init__(self, *args, **kwargs):
super(CategoryField, self).__init__(widget=CategorySelect(self.get_facebook_event_tree()), *args, **kwargs)
def get_facebook_event_tree(self):
# Output a tree structure, more easily handled by client side code
results = []
for i, category in enumerate(self.FACEBOOK_EVENTS):
category_label, slices = category
s1, s2 = slices
subcats = zip(range(*slices), self.FACEBOOK_EVENT_SUBCATEGORIES[s1:s2])
results += ((i, category_label, subcats),)
return results
def clean(self, value):
try:
if [int(b) for b in value if b]:
return value
except ValueError:
raise forms.ValidationError(_('You must select a category and subcategory for your event.'))
return [None, None]
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.