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 cachekey = [] |
|
141 pending_relations = [] |
|
142 for attr, value in kwargs.items(): |
|
143 if isinstance(value, (tuple, list, set, frozenset)): |
|
144 if len(value) == 1: |
|
145 value = iter(value).next() |
|
146 else: |
|
147 del kwargs[attr] |
|
148 pending_relations.append( (attr, value) ) |
|
149 continue |
|
150 if hasattr(value, 'eid'): # non final relation |
|
151 rvar = attr.upper() |
|
152 # XXX safer detection of object relation |
|
153 if attr.startswith('reverse_'): |
|
154 relations.append('%s %s X' % (rvar, attr[len('reverse_'):])) |
|
155 else: |
|
156 relations.append('X %s %s' % (attr, rvar)) |
|
157 restriction = '%s eid %%(%s)s' % (rvar, attr) |
|
158 if not restriction in restrictions: |
|
159 restrictions.add(restriction) |
|
160 cachekey.append(attr) |
|
161 kwargs[attr] = value.eid |
|
162 else: # attribute |
|
163 relations.append('X %s %%(%s)s' % (attr, attr)) |
|
164 if relations: |
|
165 rql = '%s: %s' % (rql, ', '.join(relations)) |
|
166 if restrictions: |
|
167 rql = '%s WHERE %s' % (rql, ', '.join(restrictions)) |
|
168 created = execute(rql, kwargs, cachekey).get_entity(0, 0) |
|
169 for attr, values in pending_relations: |
|
170 if attr.startswith('reverse_'): |
|
171 restr = 'Y %s X' % attr[len('reverse_'):] |
|
172 else: |
|
173 restr = 'X %s Y' % attr |
|
174 execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % ( |
|
175 restr, ','.join(str(r.eid) for r in values)), |
|
176 {'x': created.eid}, 'x', build_descr=False) |
|
177 return created |
|
178 |
135 |
179 def ensure_ro_rql(self, rql): |
136 def ensure_ro_rql(self, rql): |
180 """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""" |
181 first = rql.split(' ', 1)[0].lower() |
138 first = rql.split(' ', 1)[0].lower() |
182 if first in ('insert', 'set', 'delete'): |
139 if first in ('insert', 'set', 'delete'): |