[forms] propagate aguments given to .vocabulary to .choices if it's a callable.
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 27 Jan 2010 09:56:16 +0100
changeset 4388 15c6607c4bda
parent 4387 4aacd6492ef4
child 4389 14a993bc8d1e
[forms] propagate aguments given to .vocabulary to .choices if it's a callable. So we can properly uses vocabulary(limit=xxx) in places where we used to call .choices(limit), since field.choices is not meant to be accessed directly. Also, document expected behaviour for custom choices method for relation fields.
web/formfields.py
--- a/web/formfields.py	Wed Jan 27 09:53:48 2010 +0100
+++ b/web/formfields.py	Wed Jan 27 09:56:16 2010 +0100
@@ -251,7 +251,7 @@
         widget = self.get_widget(form)
         return widget.render(form, self, renderer)
 
-    def vocabulary(self, form):
+    def vocabulary(self, form, **kwargs):
         """return vocabulary for this field. This method will be called by
         widgets which requires a vocabulary.
         """
@@ -259,20 +259,20 @@
         if callable(self.choices):
             try:
                 if getattr(self.choices, 'im_self', None) is self:
-                    vocab = self.choices(form=form)
+                    vocab = self.choices(form=form, **kwargs)
                 else:
-                    vocab = self.choices(form=form, field=self)
+                    vocab = self.choices(form=form, field=self, **kwargs)
             except TypeError:
                 warn('[3.6]  %s: choices should now take '
                      'the form and field as named arguments' % self,
                      DeprecationWarning)
                 try:
-                    vocab = self.choices(form=form)
+                    vocab = self.choices(form=form, **kwargs)
                 except TypeError:
                     warn('[3.3]  %s: choices should now take '
                          'the form and field as named arguments' % self,
                          DeprecationWarning)
-                    vocab = self.choices(req=form._cw)
+                    vocab = self.choices(req=form._cw, **kwargs)
         else:
             vocab = self.choices
         if vocab and not isinstance(vocab[0], (list, tuple)):
@@ -760,13 +760,24 @@
         return RelationField(**kwargs)
 
     def choices(self, form, limit=None):
+        """Take care, choices function for relation field instance should take
+        an extra 'limit' argument, with default to None.
+
+        This argument is used by the 'unrelateddivs' view (see in autoform) and
+        when it's specified (eg not None), vocabulary returned should:
+        * not include already related entities
+        * have a max size of `limit` entities
+        """
         entity = form.edited_entity
         # first see if its specified by __linkto form parameters
-        linkedto = relvoc_linkedto(entity, self.name, self.role)
-        if linkedto:
-            return linkedto
+        if limit is None:
+            linkedto = relvoc_linkedto(entity, self.name, self.role)
+            if linkedto:
+                return linkedto
+            vocab = relvoc_init(entity, self.name, self.role, self.required)
+        else:
+            vocab = []
         # it isn't, check if the entity provides a method to get correct values
-        vocab = relvoc_init(entity, self.name, self.role, self.required)
         method = '%s_%s_vocabulary' % (self.role, self.name)
         try:
             vocab += getattr(form, method)(self.name, limit)