131 >>> create_entity('Person', firstname=u'John', lastname=u'Doe', |
128 >>> create_entity('Person', firstname=u'John', lastname=u'Doe', |
132 ... works_for=c) |
129 ... works_for=c) |
133 |
130 |
134 """ |
131 """ |
135 _check_cw_unsafe(kwargs) |
132 _check_cw_unsafe(kwargs) |
136 execute = self.execute |
133 cls = self.vreg['etypes'].etype_class(etype) |
137 rql = 'INSERT %s X' % etype |
134 return cls.cw_instantiate(self.execute, **kwargs) |
138 relations = [] |
|
139 restrictions = set() |
|
140 pending_relations = [] |
|
141 for attr, value in kwargs.items(): |
|
142 if isinstance(value, (tuple, list, set, frozenset)): |
|
143 if len(value) == 1: |
|
144 value = iter(value).next() |
|
145 else: |
|
146 del kwargs[attr] |
|
147 pending_relations.append( (attr, value) ) |
|
148 continue |
|
149 if hasattr(value, 'eid'): # non final relation |
|
150 rvar = attr.upper() |
|
151 # XXX safer detection of object relation |
|
152 if attr.startswith('reverse_'): |
|
153 relations.append('%s %s X' % (rvar, attr[len('reverse_'):])) |
|
154 else: |
|
155 relations.append('X %s %s' % (attr, rvar)) |
|
156 restriction = '%s eid %%(%s)s' % (rvar, attr) |
|
157 if not restriction in restrictions: |
|
158 restrictions.add(restriction) |
|
159 kwargs[attr] = value.eid |
|
160 else: # attribute |
|
161 relations.append('X %s %%(%s)s' % (attr, attr)) |
|
162 if relations: |
|
163 rql = '%s: %s' % (rql, ', '.join(relations)) |
|
164 if restrictions: |
|
165 rql = '%s WHERE %s' % (rql, ', '.join(restrictions)) |
|
166 created = execute(rql, kwargs).get_entity(0, 0) |
|
167 for attr, values in pending_relations: |
|
168 if attr.startswith('reverse_'): |
|
169 restr = 'Y %s X' % attr[len('reverse_'):] |
|
170 else: |
|
171 restr = 'X %s Y' % attr |
|
172 execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % ( |
|
173 restr, ','.join(str(r.eid) for r in values)), |
|
174 {'x': created.eid}, build_descr=False) |
|
175 return created |
|
176 |
135 |
177 def ensure_ro_rql(self, rql): |
136 def ensure_ro_rql(self, rql): |
178 """raise an exception if the given rql is not a select query""" |
137 """raise an exception if the given rql is not a select query""" |
179 first = rql.split(' ', 1)[0].lower() |
138 first = rql.split(' ', 1)[0].lower() |
180 if first in ('insert', 'set', 'delete'): |
139 if first in ('insert', 'set', 'delete'): |