如何检查Django中多对多字段的类型?

10 投票
4 回答
9763 浏览
提问于 2025-04-15 22:47

在Django中,怎么检查一个多对多字段的类型呢?

我想这样做:

import django  
field.__class__ == django.db.models.fields.related.ManyRelatedManager

这样做不行,因为找不到名为 ManyRelatedManager 的类。不过如果我用 field.__class__,输出的结果是 django.db.models.fields.related.ManyRelatedManager

为什么它提到一个看起来不存在的类,我该怎么才能让它正常工作呢?

非常感谢你的帮助。

4 个回答

2

(使用 Django 1.11)

这个问题变得有些混乱,因为报告的行为与现代相关字段的行为不一致。这里有个例子,其中 JobTemplate 是模型类,而 credentials 是一个多对多的相关字段:

>>> JobTemplate._meta.get_field('credentials').__class__
 django.db.models.fields.related.ManyToManyField

如果我们检查一个对象的 _meta,会有什么不同吗?

>>> JobTemplate.objects.first()._meta.get_field('credentials').__class__
django.db.models.fields.related.ManyToManyField

不会。

接下来,我想插入一个我认为最有可能的场景,可能会有人来这里。你有这个:

>>> JobTemplate.objects.first().credentials
<django.db.models.fields.related_descriptors.ManyRelatedManager at 0x6f9b390>

注意,这就是提问者所拥有的。

我会假设相关模型是 Credential。我可以检查这是否是一个相关的凭证管理器!

>>> isinstance(JobTemplate.objects.first().credentials, Credential.objects.__class__)
True

多对多字段可能很难处理,因为这个属性会自我销毁,并用管理器的子类替代。你也可以通过 get_field('credentials') 获取的字段来交叉验证这些信息,以确保准确。上面的 isinstance 检查也可能错误地识别出你在模型上设置的其他管理器。不过,这仍然是一个有价值的测试,可以看看你拥有的属性是否“像”那个特定相关模型的多对多字段应该那样工作。

20

你可以把它当作一个字符串来检查。

field.__class__.__name__ == 'ManyRelatedManager'
7

如果你已经有了字段实例,你可以直接这样做:

if isinstance(field, ManyToManyField):
    pass // stuff

如果你只有相关的管理器实例,你可以反向查找字段实例:

>>> print fm
<class 'django.db.models.fields.related.ManyRelatedManager'>
>>> print fm.instance._meta.get_field_by_name('fieldnamehere')
(<django.db.models.fields.related.ForeignKey: fieldnamehere>, None, True, False)

这个方法只在Django 1.5上测试过。

撰写回答