Creates the default empty through model.
Generates a middle model based on the owner of the field and the field itself and adds
it to the main registry to make sure it generates the proper models and migrations.
Source code in saffier/core/db/fields/base.py
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460 | def create_through_model(self) -> typing.Any:
"""
Creates the default empty through model.
Generates a middle model based on the owner of the field and the field itself and adds
it to the main registry to make sure it generates the proper models and migrations.
"""
self.to = typing.cast(typing.Type["Model"], self.target)
if self.through:
if isinstance(self.through, str):
self.through = self.owner.meta.registry.models[self.through] # type: ignore
self.through.meta.is_multi = True
self.through.meta.multi_related = [self.to.__name__.lower()]
return self.through
owner_name = self.owner.__name__
to_name = self.to.__name__
class_name = f"{owner_name}{to_name}"
tablename = f"{owner_name.lower()}s_{to_name}s".lower()
new_meta_namespace = {
"tablename": tablename,
"registry": self.owner.meta.registry,
"is_multi": True,
"multi_related": [to_name.lower()],
}
new_meta = type("MetaInfo", (), new_meta_namespace)
# Define the related names
owner_related_name = (
f"{self.related_name}_{class_name.lower()}s_set"
if self.related_name
else f"{owner_name.lower()}_{class_name.lower()}s_set"
)
to_related_name = (
f"{self.related_name}"
if self.related_name
else f"{to_name.lower()}_{class_name.lower()}s_set"
)
through_model = type(
class_name,
(saffier.Model,),
{
"Meta": new_meta,
"id": saffier.IntegerField(primary_key=True),
f"{owner_name.lower()}": ForeignKey(
self.owner,
on_delete=saffier.CASCADE,
null=True,
related_name=owner_related_name,
),
f"{to_name.lower()}": ForeignKey(
self.to, on_delete=saffier.CASCADE, null=True, related_name=to_related_name
),
},
)
self.through = typing.cast(typing.Type["Model"], through_model)
self.add_model_to_register(self.through)
|