web/formfields.py
changeset 7875 65e460690139
parent 7756 98e34ae4cf89
child 7894 ad0eeb0f7a8d
equal deleted inserted replaced
7871:29fc83fca803 7875:65e460690139
  1016         # error when processed by the editcontroller : it may be marked as required
  1016         # error when processed by the editcontroller : it may be marked as required
  1017         # while it has no value, hence generating a false error.
  1017         # while it has no value, hence generating a false error.
  1018         return list(self.fields)
  1018         return list(self.fields)
  1019 
  1019 
  1020 
  1020 
  1021 # relation vocabulary helper functions #########################################
       
  1022 
       
  1023 def relvoc_linkedto(entity, rtype, role):
       
  1024     # first see if its specified by __linkto form parameters
       
  1025     linkedto = entity.linked_to(rtype, role)
       
  1026     if linkedto:
       
  1027         buildent = entity._cw.entity_from_eid
       
  1028         return [(buildent(eid).view('combobox'), unicode(eid)) for eid in linkedto]
       
  1029     return []
       
  1030 
       
  1031 def relvoc_init(entity, rtype, role, required=False):
       
  1032     # it isn't, check if the entity provides a method to get correct values
       
  1033     vocab = []
       
  1034     if not required:
       
  1035         vocab.append(('', INTERNAL_FIELD_VALUE))
       
  1036     # vocabulary doesn't include current values, add them
       
  1037     if entity.has_eid():
       
  1038         rset = entity.related(rtype, role)
       
  1039         vocab += [(e.view('combobox'), unicode(e.eid)) for e in rset.entities()]
       
  1040     return vocab
       
  1041 
       
  1042 def relvoc_unrelated(entity, rtype, role, limit=None):
       
  1043     if isinstance(rtype, basestring):
       
  1044         rtype = entity._cw.vreg.schema.rschema(rtype)
       
  1045     if entity.has_eid():
       
  1046         done = set(row[0] for row in entity.related(rtype, role))
       
  1047     else:
       
  1048         done = None
       
  1049     result = []
       
  1050     rsetsize = None
       
  1051     for objtype in rtype.targets(entity.e_schema, role):
       
  1052         if limit is not None:
       
  1053             rsetsize = limit - len(result)
       
  1054         result += _relvoc_unrelated(entity, rtype, objtype, role, rsetsize, done)
       
  1055         if limit is not None and len(result) >= limit:
       
  1056             break
       
  1057     return result
       
  1058 
       
  1059 def _relvoc_unrelated(entity, rtype, targettype, role, limit, done):
       
  1060     """return unrelated entities for a given relation and target entity type
       
  1061     for use in vocabulary
       
  1062     """
       
  1063     if done is None:
       
  1064         done = set()
       
  1065     res = []
       
  1066     for entity in entity.unrelated(rtype, targettype, role, limit).entities():
       
  1067         if entity.eid in done:
       
  1068             continue
       
  1069         done.add(entity.eid)
       
  1070         res.append((entity.view('combobox'), unicode(entity.eid)))
       
  1071     return res
       
  1072 
       
  1073 
       
  1074 class RelationField(Field):
  1021 class RelationField(Field):
  1075     """Use this field to edit a relation of an entity.
  1022     """Use this field to edit a relation of an entity.
  1076 
  1023 
  1077     Unless explicitly specified, the widget for this field will be a
  1024     Unless explicitly specified, the widget for this field will be a
  1078     :class:`~cubicweb.web.formwidgets.Select`.
  1025     :class:`~cubicweb.web.formwidgets.Select`.
  1093         * have a max size of `limit` entities
  1040         * have a max size of `limit` entities
  1094         """
  1041         """
  1095         entity = form.edited_entity
  1042         entity = form.edited_entity
  1096         # first see if its specified by __linkto form parameters
  1043         # first see if its specified by __linkto form parameters
  1097         if limit is None:
  1044         if limit is None:
  1098             linkedto = relvoc_linkedto(entity, self.name, self.role)
  1045             linkedto = self.relvoc_linkedto(form)
  1099             if linkedto:
  1046             if linkedto:
  1100                 return linkedto
  1047                 return linkedto
  1101             vocab = relvoc_init(entity, self.name, self.role, self.required)
  1048             vocab = self.relvoc_init(form)
  1102         else:
  1049         else:
  1103             vocab = []
  1050             vocab = []
  1104         # it isn't, check if the entity provides a method to get correct values
  1051         # it isn't, check if the entity provides a method to get correct values
  1105         method = '%s_%s_vocabulary' % (self.role, self.name)
  1052         method = '%s_%s_vocabulary' % (self.role, self.name)
  1106         try:
  1053         try:
  1107             vocab += getattr(form, method)(self.name, limit)
  1054             vocab += getattr(form, method)(self.name, limit)
  1108             warn('[3.6] found %s on %s, should override field.choices instead (need tweaks)'
  1055             warn('[3.6] found %s on %s, should override field.choices instead (need tweaks)'
  1109                  % (method, form), DeprecationWarning)
  1056                  % (method, form), DeprecationWarning)
  1110         except AttributeError:
  1057         except AttributeError:
  1111             vocab += relvoc_unrelated(entity, self.name, self.role, limit)
  1058             vocab += self.relvoc_unrelated(form, limit)
  1112         if self.sort:
  1059         if self.sort:
  1113             vocab = vocab_sort(vocab)
  1060             vocab = vocab_sort(vocab)
  1114         return vocab
  1061         return vocab
  1115 
  1062 
  1116     def form_init(self, form):
  1063     def relvoc_linkedto(self, form):
  1117         #if not self.display_value(form):
  1064         linkedto = form.linked_to.get((self.name, self.role))
  1118         value = form.edited_entity.linked_to(self.name, self.role)
  1065         if linkedto:
  1119         if value:
  1066             buildent = form._cw.entity_from_eid
  1120             searchedvalues = ['%s:%s:%s' % (self.name, eid, self.role)
  1067             return [(buildent(eid).view('combobox'), unicode(eid))
  1121                               for eid in value]
  1068                     for eid in linkedto]
  1122             # remove associated __linkto hidden fields
  1069         return []
  1123             for field in form.root_form.fields_by_name('__linkto'):
  1070 
  1124                 if field.value in searchedvalues:
  1071     def relvoc_init(self, form):
  1125                     form.root_form.remove_field(field)
  1072         entity, rtype, role = form.edited_entity, self.name, self.role
  1126             form.formvalues[(self, form)] = value
  1073         vocab = []
       
  1074         if not self.required:
       
  1075             vocab.append(('', INTERNAL_FIELD_VALUE))
       
  1076         # vocabulary doesn't include current values, add them
       
  1077         if form.edited_entity.has_eid():
       
  1078             rset = form.edited_entity.related(self.name, self.role)
       
  1079             vocab += [(e.view('combobox'), unicode(e.eid))
       
  1080                       for e in rset.entities()]
       
  1081         return vocab
       
  1082 
       
  1083     def relvoc_unrelated(self, form, limit=None):
       
  1084         entity = form.edited_entity
       
  1085         rtype = entity._cw.vreg.schema.rschema(self.name)
       
  1086         if entity.has_eid():
       
  1087             done = set(row[0] for row in entity.related(rtype, self.role))
       
  1088         else:
       
  1089             done = None
       
  1090         result = []
       
  1091         rsetsize = None
       
  1092         for objtype in rtype.targets(entity.e_schema, self.role):
       
  1093             if limit is not None:
       
  1094                 rsetsize = limit - len(result)
       
  1095             result += self._relvoc_unrelated(form, objtype, rsetsize, done)
       
  1096             if limit is not None and len(result) >= limit:
       
  1097                 break
       
  1098         return result
       
  1099 
       
  1100     def _relvoc_unrelated(self, form, targettype, limit, done):
       
  1101         """return unrelated entities for a given relation and target entity type
       
  1102         for use in vocabulary
       
  1103         """
       
  1104         if done is None:
       
  1105             done = set()
       
  1106         res = []
       
  1107         entity = form.edited_entity
       
  1108         for entity in entity.unrelated(self.name, targettype,
       
  1109                                        self.role, limit).entities():
       
  1110             if entity.eid in done:
       
  1111                 continue
       
  1112             done.add(entity.eid)
       
  1113             res.append((entity.view('combobox'), unicode(entity.eid)))
       
  1114         return res
  1127 
  1115 
  1128     def format_single_value(self, req, value):
  1116     def format_single_value(self, req, value):
  1129         return unicode(value)
  1117         return unicode(value)
  1130 
  1118 
  1131     def process_form_value(self, form):
  1119     def process_form_value(self, form):