python - 如何在 Django 自定义模型管理器中访问相关模型?
问题描述
我有以下三个模型
models.py
:
class Activity(models.Model):
# ...
objects = models.Manager()
activity = ActivityManager()
kind = models.CharField(max_length=10, choices=KIND_CHOICES)
# ...
class ActivtyA(models.Model):
# ...
activity = models.OneToOneField(
Activity,
on_delete=models.CASCADE,
related_name='A',
)
# ...
class ActivtyB(models.Model):
# ...
activity = models.OneToOneField(
Activity,
on_delete=models.CASCADE,
related_name='B',
)
# ...
和模型经理
managers.py
:
class ActivityManager(models.Manager):
def create_activity(self, validated_data):
# ...
data = validated_data.pop(kind)
act = self.create(**validated_data)
if act.kind == 'A':
# Create ActivityA(act, **data)
elif act.kind == 'B':
# Create ActivityB(act, **data)
# ...
# ...
在模型管理器的方法中,create_activity
我想创建Activty
或者基于. 如果我在管理器中导入这些类,则会导致循环导入错误。我如何访问和在管理器中?ActivityA
ActivtyB
Activity.kind
ActivityA
ActivtyB
我试图通过使用信号来做到这一点,但无法做到。
@receiver(post_save, sender=Activity)
def create_activity_details(sender, instance, using, **kwargs):
if instance.kind == 'A':
ActivityA.objects.create(activity=instance, data=????) # Need data to create this object
elif instance.kind == 'A':
ActivityB.objects.create(activity=instance, data=????)
解决方案
所以,我去了老学校,这样做是为了让它发挥作用,
data = validated_data.pop(kind)
act = self.create(**validated_data)
if act.kind == 'A':
from activity.models import ActivityA # Prevent the circular import
ActivityA.objects.create(activity=act, **data)
elif act.kind == 'B':
from activity.models import ActivityB
ActivityB.objects.create(activity=act, **data)
它有效,但看起来并不干净。还有其他更好的解决方案吗?
更新:
所以,使用django.apps.apps.get_model
就是答案。感谢@djvj为我指明了正确的方向。
医生说:
apps.get_model(app_label, model_name, require_ready=True)
返回具有给定app_label
和的模型model_name
。作为一种快捷方式,此方法还接受表单中的单个参数app_label.model_name
。model_name
不区分大小写。
例子:
from django.apps import apps
class ActivityManager(models.Manager):
def create_activity(self, validated_data):
# ...
data = validated_data.pop(kind)
act = self.create(**validated_data)
if act.kind == 'A':
model = apps.get_model(app_label='activity', model_name='ActivityA')
model.objects.create(activity=act, **data)
elif act.kind == 'B':
model = apps.get_model(app_label='activity', model_name='ActivityB')
model.objects.create(activity=act, **data)
# ...
# ...
apps.get_model(app_label='activity', model_name='ActivityA')
可以简单地写成
apps.get_model('activity.ActivityA')
推荐阅读
- r - 我觉得很难理解数组维度的概念
- twig - loop.index 返回 NaN
- qt - QML TableView 鼠标区域不会将点击传播到选择模型
- ruby-on-rails - 在两个不同的地方,从两个不同的控制器渲染部分轨道
- visual-studio-code - textMateRules 用于参数和参数用法语法高亮
- python - 从一堆单独的系列中构建一个 Pandas 多索引数据框
- javascript - 在对象数组中添加对象(对象是多维的)
- android - 安卓。需要访问用户的电子邮件
- java - 自定义登录表单无法使用 Spring Security
- c# - Serilog 不登录到 .NET Core 2.1 中的控制台