MCPcopy
hub / github.com/tortoise/tortoise-orm / add

Method add

tortoise/fields/relational.py:177–220  ·  view source on GitHub ↗

Adds one or more of ``instances`` to the relation. If it is already added, it will be silently ignored. :raises OperationalError: If Object to add is not saved.

(self, *instances: MODEL, using_db: BaseDBAsyncClient | None = None)

Source from the content-addressed store, hash-verified

175 self.instance = instance
176
177 async def add(self, *instances: MODEL, using_db: BaseDBAsyncClient | None = None) -> None:
178 """
179 Adds one or more of ``instances`` to the relation.
180
181 If it is already added, it will be silently ignored.
182
183 :raises OperationalError: If Object to add is not saved.
184 """
185 if not instances:
186 return
187 if not self.instance._saved_in_db:
188 raise OperationalError(f"You should first call .save() on {self.instance}")
189 db = using_db or self.remote_model._meta.db
190 pk_formatting_func = type(self.instance)._meta.pk.to_db_value
191 related_pk_formatting_func = type(instances[0])._meta.pk.to_db_value
192 pk_b = pk_formatting_func(self.instance.pk, self.instance)
193 pks_f: list = []
194 for instance_to_add in instances:
195 if not instance_to_add._saved_in_db:
196 raise OperationalError(f"You should first call .save() on {instance_to_add}")
197 pk_f = related_pk_formatting_func(instance_to_add.pk, instance_to_add)
198 pks_f.append(pk_f)
199 through_table = Table(self.field.through, schema=self.field.through_schema)
200 backward_key, forward_key = self.field.backward_key, self.field.forward_key
201 backward_field, forward_field = through_table[backward_key], through_table[forward_key]
202 select_query = (
203 db.query_class.from_(through_table).where(backward_field == pk_b).select(forward_key)
204 )
205 criterion = forward_field == pks_f[0] if len(pks_f) == 1 else forward_field.isin(pks_f)
206 select_query = select_query.where(criterion)
207
208 _, already_existing_relations_raw = await db.execute_query(
209 *select_query.get_parameterized_sql()
210 )
211 already_existing_forward_pks = {
212 related_pk_formatting_func(r[forward_key], self.instance)
213 for r in already_existing_relations_raw
214 }
215
216 if pks_f_to_insert := set(pks_f) - already_existing_forward_pks:
217 query = db.query_class.into(through_table).columns(forward_field, backward_field)
218 for pk_f in pks_f_to_insert:
219 query = query.insert(pk_f, pk_b)
220 await db.execute_query(*query.get_parameterized_sql())
221
222 async def clear(self, using_db: BaseDBAsyncClient | None = None) -> None:
223 """

Callers 15

resolve_for_querysetMethod · 0.80
select_relatedMethod · 0.80
force_indexMethod · 0.80
use_indexMethod · 0.80
prefetch_relatedMethod · 0.80
_resolve_onlyMethod · 0.80
add_fieldMethod · 0.80
_dispatch_fieldsMethod · 0.80
_set_kwargsMethod · 0.80
constructMethod · 0.80
_topological_sort_modelsFunction · 0.80

Calls 3

OperationalErrorClass · 0.90
get_parameterized_sqlMethod · 0.80
execute_queryMethod · 0.45