web/views/editcontroller.py
changeset 3451 6b46d73823f5
parent 3396 fb261afd49cd
child 3463 bc2ee1d059fd
equal deleted inserted replaced
3448:495862266785 3451:6b46d73823f5
    51 class EditController(ViewController):
    51 class EditController(ViewController):
    52     __regid__ = 'edit'
    52     __regid__ = 'edit'
    53 
    53 
    54     def publish(self, rset=None):
    54     def publish(self, rset=None):
    55         """edit / create / copy / delete entity / relations"""
    55         """edit / create / copy / delete entity / relations"""
    56         for key in self.req.form:
    56         for key in self._cw.form:
    57             # There should be 0 or 1 action
    57             # There should be 0 or 1 action
    58             if key.startswith('__action_'):
    58             if key.startswith('__action_'):
    59                 cbname = key[1:]
    59                 cbname = key[1:]
    60                 try:
    60                 try:
    61                     callback = getattr(self, cbname)
    61                     callback = getattr(self, cbname)
    62                 except AttributeError:
    62                 except AttributeError:
    63                     raise RequestError(self.req._('invalid action %r' % key))
    63                     raise RequestError(self._cw._('invalid action %r' % key))
    64                 else:
    64                 else:
    65                     return callback()
    65                     return callback()
    66         self._default_publish()
    66         self._default_publish()
    67         self.reset()
    67         self.reset()
    68 
    68 
    69     def _default_publish(self):
    69     def _default_publish(self):
    70         req = self.req
    70         req = self._cw
    71         self.errors = []
    71         self.errors = []
    72         self.relations_rql = []
    72         self.relations_rql = []
    73         # no specific action, generic edition
    73         # no specific action, generic edition
    74         self._to_create = req.data['eidmap'] = {}
    74         self._to_create = req.data['eidmap'] = {}
    75         self._pending_relations = []
    75         self._pending_relations = []
    76         todelete = self.req.get_pending_deletes()
    76         todelete = self._cw.get_pending_deletes()
    77         toinsert = self.req.get_pending_inserts()
    77         toinsert = self._cw.get_pending_inserts()
    78         try:
    78         try:
    79             methodname = req.form.pop('__method', None)
    79             methodname = req.form.pop('__method', None)
    80             for eid in req.edited_eids():
    80             for eid in req.edited_eids():
    81                 # __type and eid
    81                 # __type and eid
    82                 formparams = req.extract_entity_params(eid, minparams=2)
    82                 formparams = req.extract_entity_params(eid, minparams=2)
    89             if '__linkto' in req.form and 'eid' in req.form:
    89             if '__linkto' in req.form and 'eid' in req.form:
    90                 self.execute_linkto()
    90                 self.execute_linkto()
    91             elif not ('__delete' in req.form or '__insert' in req.form or todelete or toinsert):
    91             elif not ('__delete' in req.form or '__insert' in req.form or todelete or toinsert):
    92                 raise ValidationError(None, {None: req._('nothing to edit')})
    92                 raise ValidationError(None, {None: req._('nothing to edit')})
    93         for querydef in self.relations_rql:
    93         for querydef in self.relations_rql:
    94             self.req.execute(*querydef)
    94             self._cw.execute(*querydef)
    95         # handle relations in newly created entities
    95         # handle relations in newly created entities
    96         # XXX find a way to merge _pending_relations and relations_rql
    96         # XXX find a way to merge _pending_relations and relations_rql
    97         if self._pending_relations:
    97         if self._pending_relations:
    98             for form, field, entity in self._pending_relations:
    98             for form, field, entity in self._pending_relations:
    99                 for querydef in self.handle_relation(form, field, entity, True):
    99                 for querydef in self.handle_relation(form, field, entity, True):
   100                     self.req.execute(*querydef)
   100                     self._cw.execute(*querydef)
   101         # XXX this processes *all* pending operations of *all* entities
   101         # XXX this processes *all* pending operations of *all* entities
   102         if req.form.has_key('__delete'):
   102         if req.form.has_key('__delete'):
   103             todelete += req.list_form_param('__delete', req.form, pop=True)
   103             todelete += req.list_form_param('__delete', req.form, pop=True)
   104         if todelete:
   104         if todelete:
   105             self.delete_relations(parse_relations_descr(todelete))
   105             self.delete_relations(parse_relations_descr(todelete))
   106         if req.form.has_key('__insert'):
   106         if req.form.has_key('__insert'):
   107             toinsert = req.list_form_param('__insert', req.form, pop=True)
   107             toinsert = req.list_form_param('__insert', req.form, pop=True)
   108         if toinsert:
   108         if toinsert:
   109             self.insert_relations(parse_relations_descr(toinsert))
   109             self.insert_relations(parse_relations_descr(toinsert))
   110         self.req.remove_pending_operations()
   110         self._cw.remove_pending_operations()
   111 
   111 
   112     def _insert_entity(self, etype, eid, rqlquery):
   112     def _insert_entity(self, etype, eid, rqlquery):
   113         rql = rqlquery.insert_query(etype)
   113         rql = rqlquery.insert_query(etype)
   114         try:
   114         try:
   115             # get the new entity (in some cases, the type might have
   115             # get the new entity (in some cases, the type might have
   116             # changed as for the File --> Image mutation)
   116             # changed as for the File --> Image mutation)
   117             entity = self.req.execute(rql, rqlquery.kwargs).get_entity(0, 0)
   117             entity = self._cw.execute(rql, rqlquery.kwargs).get_entity(0, 0)
   118             neweid = entity.eid
   118             neweid = entity.eid
   119         except ValidationError, ex:
   119         except ValidationError, ex:
   120             self._to_create[eid] = ex.entity
   120             self._to_create[eid] = ex.entity
   121             if self.req.json_request: # XXX (syt) why?
   121             if self._cw.json_request: # XXX (syt) why?
   122                 ex.entity = eid
   122                 ex.entity = eid
   123             raise
   123             raise
   124         self._to_create[eid] = neweid
   124         self._to_create[eid] = neweid
   125         return neweid
   125         return neweid
   126 
   126 
   127     def _update_entity(self, eid, rqlquery):
   127     def _update_entity(self, eid, rqlquery):
   128         rql = rqlquery.update_query(eid)
   128         rql = rqlquery.update_query(eid)
   129         self.req.execute(rql, rqlquery.kwargs)
   129         self._cw.execute(rql, rqlquery.kwargs)
   130 
   130 
   131     def edit_entity(self, formparams, multiple=False):
   131     def edit_entity(self, formparams, multiple=False):
   132         """edit / create / copy an entity and return its eid"""
   132         """edit / create / copy an entity and return its eid"""
   133         etype = formparams['__type']
   133         etype = formparams['__type']
   134         entity = self.vreg['etypes'].etype_class(etype)(self.req)
   134         entity = self._cw.vreg['etypes'].etype_class(etype)(self._cw)
   135         entity.eid = formparams['eid']
   135         entity.eid = formparams['eid']
   136         eid = self._get_eid(entity.eid)
   136         eid = self._get_eid(entity.eid)
   137         is_main_entity = self.req.form.get('__maineid') == formparams['eid']
   137         is_main_entity = self._cw.form.get('__maineid') == formparams['eid']
   138         # let a chance to do some entity specific stuff.tn
   138         # let a chance to do some entity specific stuff.tn
   139         entity.pre_web_edit()
   139         entity.pre_web_edit()
   140         # create a rql query from parameters
   140         # create a rql query from parameters
   141         rqlquery = RqlQuery()
   141         rqlquery = RqlQuery()
   142         # process inlined relations at the same time as attributes
   142         # process inlined relations at the same time as attributes
   143         # this will generate less rql queries and might be useful in
   143         # this will generate less rql queries and might be useful in
   144         # a few dark corners
   144         # a few dark corners
   145         formid = self.req.form.get('__form_id', 'edition')
   145         formid = self._cw.form.get('__form_id', 'edition')
   146         form = self.vreg['forms'].select(formid, self.req, entity=entity)
   146         form = self._cw.vreg['forms'].select(formid, self._cw, entity=entity)
   147         for field in form.fields:
   147         for field in form.fields:
   148             if form.form_field_modified(field):
   148             if form.form_field_modified(field):
   149                 self.handle_formfield(form, field, entity, rqlquery)
   149                 self.handle_formfield(form, field, entity, rqlquery)
   150         if eid is None: # creation or copy
   150         if eid is None: # creation or copy
   151             entity.eid = self._insert_entity(etype, formparams['eid'], rqlquery)
   151             entity.eid = self._insert_entity(etype, formparams['eid'], rqlquery)
   152         elif rqlquery.edited: # edition of an existant entity
   152         elif rqlquery.edited: # edition of an existant entity
   153             self._update_entity(eid, rqlquery)
   153             self._update_entity(eid, rqlquery)
   154         if is_main_entity:
   154         if is_main_entity:
   155             self.notify_edited(entity)
   155             self.notify_edited(entity)
   156         if formparams.has_key('__delete'):
   156         if formparams.has_key('__delete'):
   157             todelete = self.req.list_form_param('__delete', formparams, pop=True)
   157             todelete = self._cw.list_form_param('__delete', formparams, pop=True)
   158             self.delete_relations(parse_relations_descr(todelete))
   158             self.delete_relations(parse_relations_descr(todelete))
   159         if formparams.has_key('__cloned_eid'):
   159         if formparams.has_key('__cloned_eid'):
   160             entity.copy_relations(formparams['__cloned_eid'])
   160             entity.copy_relations(formparams['__cloned_eid'])
   161         if formparams.has_key('__insert'):
   161         if formparams.has_key('__insert'):
   162             toinsert = self.req.list_form_param('__insert', formparams, pop=True)
   162             toinsert = self._cw.list_form_param('__insert', formparams, pop=True)
   163             self.insert_relations(parse_relations_descr(toinsert))
   163             self.insert_relations(parse_relations_descr(toinsert))
   164         if is_main_entity: # only execute linkto for the main entity
   164         if is_main_entity: # only execute linkto for the main entity
   165             self.execute_linkto(eid)
   165             self.execute_linkto(eid)
   166         return eid
   166         return eid
   167 
   167 
   172                 if not (
   172                 if not (
   173                     (field.role == 'subject' and eschema.has_subject_relation(field.name))
   173                     (field.role == 'subject' and eschema.has_subject_relation(field.name))
   174                     or
   174                     or
   175                     (field.role == 'object' and eschema.has_object_relation(field.name))):
   175                     (field.role == 'object' and eschema.has_object_relation(field.name))):
   176                     continue
   176                     continue
   177                 rschema = self.schema.rschema(field.name)
   177                 rschema = self._cw.schema.rschema(field.name)
   178                 if rschema.is_final():
   178                 if rschema.is_final():
   179                     rqlquery.kwargs[attr] = value
   179                     rqlquery.kwargs[attr] = value
   180                     rqlquery.edited.append('X %s %%(%s)s' % (attr, attr))
   180                     rqlquery.edited.append('X %s %%(%s)s' % (attr, attr))
   181                 elif rschema.inlined:
   181                 elif rschema.inlined:
   182                     self.handle_inlined_relation(form, field, entity, rqlquery)
   182                     self.handle_inlined_relation(form, field, entity, rqlquery)
   189     def _action_apply(self):
   189     def _action_apply(self):
   190         self._default_publish()
   190         self._default_publish()
   191         self.reset()
   191         self.reset()
   192 
   192 
   193     def _action_cancel(self):
   193     def _action_cancel(self):
   194         errorurl = self.req.form.get('__errorurl')
   194         errorurl = self._cw.form.get('__errorurl')
   195         if errorurl:
   195         if errorurl:
   196             self.req.cancel_edition(errorurl)
   196             self._cw.cancel_edition(errorurl)
   197         self.req.message = self.req._('edit canceled')
   197         self._cw.message = self._cw._('edit canceled')
   198         return self.reset()
   198         return self.reset()
   199 
   199 
   200     def _action_delete(self):
   200     def _action_delete(self):
   201         self.delete_entities(self.req.edited_eids(withtype=True))
   201         self.delete_entities(self._cw.edited_eids(withtype=True))
   202         return self.reset()
   202         return self.reset()
   203 
   203 
   204     def _relation_values(self, form, field, entity, late=False):
   204     def _relation_values(self, form, field, entity, late=False):
   205         """handle edition for the (rschema, x) relation of the given entity
   205         """handle edition for the (rschema, x) relation of the given entity
   206         """
   206         """
   240         origvalues = set(row[0] for row in entity.related(field.name, field.role))
   240         origvalues = set(row[0] for row in entity.related(field.name, field.role))
   241         values  = self._relation_values(form, field, entity, late)
   241         values  = self._relation_values(form, field, entity, late)
   242         if values is None or values == origvalues:
   242         if values is None or values == origvalues:
   243             return # not edited / not modified / to do later
   243             return # not edited / not modified / to do later
   244         etype = entity.e_schema
   244         etype = entity.e_schema
   245         rschema = self.schema.rschema(field.name)
   245         rschema = self._cw.schema.rschema(field.name)
   246         if field.role == 'subject':
   246         if field.role == 'subject':
   247             desttype = rschema.objects(etype)[0]
   247             desttype = rschema.objects(etype)[0]
   248             card = rschema.rproperty(etype, desttype, 'cardinality')[0]
   248             card = rschema.rproperty(etype, desttype, 'cardinality')[0]
   249             subjvar, objvar = 'X', 'Y'
   249             subjvar, objvar = 'X', 'Y'
   250         else:
   250         else: