88
99from ietf .doc .models import Document , DocAlias
1010
11- def tokeninput_id_doc_name_json (objs ):
12- return json .dumps ([{ "id" : o .pk , "name " : escape (o .name ) } for o in objs ])
11+ def select2_id_doc_name_json (objs ):
12+ return json .dumps ([{ "id" : o .pk , "text " : escape (o .name ) } for o in objs ])
1313
14- class AutocompletedDocumentsField (forms .CharField ):
15- """Tokenizing autocompleted multi-select field for choosing
16- documents using jquery.tokeninput .js.
14+ class SearchableDocumentsField (forms .CharField ):
15+ """Server-based multi-select field for choosing documents using
16+ select2 .js.
1717
1818 The field uses a comma-separated list of primary keys in a
19- CharField element as its API, the tokeninput Javascript adds some
20- selection magic on top of this so we have to pass it a JSON
21- representation of ids and user-understandable labels."""
19+ CharField element as its API with some extra attributes used by
20+ the Javascript part."""
2221
2322 def __init__ (self ,
2423 max_entries = None , # max number of selected objs
@@ -31,39 +30,45 @@ def __init__(self,
3130 self .doc_type = doc_type
3231 self .model = model
3332
34- super (AutocompletedDocumentsField , self ).__init__ (* args , ** kwargs )
33+ super (SearchableDocumentsField , self ).__init__ (* args , ** kwargs )
3534
36- self .widget .attrs ["class" ] = "tokenized -field"
37- self .widget .attrs ["data-hint-text " ] = hint_text
35+ self .widget .attrs ["class" ] = "select2 -field"
36+ self .widget .attrs ["data-placeholder " ] = hint_text
3837 if self .max_entries != None :
3938 self .widget .attrs ["data-max-entries" ] = self .max_entries
4039
41- def parse_tokenized_value (self , value ):
40+ def parse_select2_value (self , value ):
4241 return [x .strip () for x in value .split ("," ) if x .strip ()]
4342
4443 def prepare_value (self , value ):
4544 if not value :
4645 value = ""
4746 if isinstance (value , basestring ):
48- pks = self .parse_tokenized_value (value )
49- value = self .model .objects .filter (pk__in = pks , type = self .doc_type )
47+ pks = self .parse_select2_value (value )
48+ value = self .model .objects .filter (pk__in = pks )
49+ filter_args = {}
50+ if self .model == DocAlias :
51+ filter_args ["document__type" ] = self .doc_type
52+ else :
53+ filter_args ["type" ] = self .doc_type
54+ value = value .filter (** filter_args )
5055 if isinstance (value , self .model ):
5156 value = [value ]
5257
53- self .widget .attrs ["data-pre" ] = tokeninput_id_doc_name_json (value )
58+ self .widget .attrs ["data-pre" ] = select2_id_doc_name_json (value )
5459
5560 # doing this in the constructor is difficult because the URL
5661 # patterns may not have been fully constructed there yet
57- self .widget .attrs ["data-ajax-url" ] = urlreverse ("ajax_tokeninput_search_docs " , kwargs = {
62+ self .widget .attrs ["data-ajax-url" ] = urlreverse ("ajax_select2_search_docs " , kwargs = {
5863 "doc_type" : self .doc_type ,
5964 "model_name" : self .model .__name__ .lower ()
6065 })
6166
62- return "," .join (o .pk for o in value )
67+ return u "," .join (unicode ( o .pk ) for o in value )
6368
6469 def clean (self , value ):
65- value = super (AutocompletedDocumentsField , self ).clean (value )
66- pks = self .parse_tokenized_value (value )
70+ value = super (SearchableDocumentsField , self ).clean (value )
71+ pks = self .parse_select2_value (value )
6772
6873 objs = self .model .objects .filter (pk__in = pks )
6974
@@ -77,7 +82,7 @@ def clean(self, value):
7782
7883 return objs
7984
80- class AutocompletedDocAliasField ( AutocompletedDocumentsField ):
85+ class SearchableDocAliasesField ( SearchableDocumentsField ):
8186 def __init__ (self , model = DocAlias , * args , ** kwargs ):
82- super (AutocompletedDocAliasField , self ).__init__ (model = model , * args , ** kwargs )
87+ super (SearchableDocAliasesField , self ).__init__ (model = model , * args , ** kwargs )
8388
0 commit comments