python - Django使用 'through'关系表从模型中获取所有相关对象

标签 python django django-models python-3.5 django-1.10

在我们的应用程序中,我们有几个关系和几个模型,我试图实现一种通用方法来获取一个对象的所有相关对象,甚至是反向对象。

如果我打印 ._meta.get_fields()来自我的模型 Pessoa ,我得到了这些关系字段(我省略了“正常”字段):

<ManyToManyRel: cadastroimoveis.pessoa>
<ManyToOneRel: cadastroimoveis.pessoa_pessoa>
<ManyToOneRel: cadastroimoveis.pessoa_pessoa>
<ManyToOneRel: cadastroimoveis.pessoa_itr>
<ManyToManyRel: cadastroimoveis.doc>
<ManyToOneRel: cadastroimoveis.doc_pessoa>
cadastroimoveis.Pessoa.relacoes
cadastroimoveis.Pessoa.itrs

此特定模型仅具有 M2M 关系,并且所有这些关系都包含指定的“直通”模型 Here .

如您所见,它重复了它们,一个用于模型,另一个用于“通过”中间表(我猜也是一个模型)。在递归关系的情况下,它重复两次。

我的问题是,有没有办法让这些不重复?

一种知道哪些重复字段最终“指向”相同关系的方法(即使它向两个表发送垃圾邮件)?因为如果直通表有字段,我想以不同的方式显示它们。

并根据 Model _meta API文档,您将使用它来获取所有相关对象:
[
    f for f in MyModel._meta.get_fields()
    if (f.one_to_many or f.one_to_one)
    and f.auto_created and not f.concrete
]

但是“通过”表不被认为是 auto_created 并且是具体的。

示例:
<ManyToManyRel: cadastroimoveis.ccir>
<ManyToOneRel: cadastroimoveis.ccir_pessoa>

这两个字段“指向”相同的关系,一个是中间表,另一个是模型,有没有(自动)方法知道这两个是相关的?我找不到他们共享的任何属性。

这样做的原因是因为当直通表有字段时,我需要对其进行编辑,而不是模型本身的 M2M 字段

模型.py :http://pastebin.com/szDfhHQ3我尽我所能清洁

最佳答案

例如,我们有这组模型。我是从 this django example 捡到的.

class Person(models.Model):
    name = models.CharField(max_length=50)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(
        Person,
        through='Membership',
        through_fields=('group', 'person'),
    )

class Membership(models.Model):
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    inviter = models.ForeignKey(
        Person,
        on_delete=models.CASCADE,
        related_name="membership_invites",
    )
    invite_reason = models.CharField(max_length=64)

该解决方案看起来有点难看,但可以根据您的需要进行优化。
def get_through_field(f):                                                                                              
    opts = f.through._meta                                                                                             
    if f.through_fields:
        return opts.get_field(f.through_fields[1])                                                                     
    for field in opts.fields:                                                                                          
        rel = getattr(field, 'remote_field', None)                                                                     
        if rel and rel.model == f.model:                                                                               
            return field

model = models.Person

rels = dict(
    (f.field, f) for f in model._meta.get_fields()
    if f.is_relation
)

excludes = set()
for f in model._meta.get_fields():
    if f.many_to_many:
        through = get_through_field(f)
        excludes.add(rels[through])

for f in model._meta.get_fields():
    if f not in excludes:
        print f.name, f

输出 :
group <ManyToManyRel: m.group>
membership_invites <ManyToOneRel: m.membership>
id m.Person.id
name m.Person.name

如您所见,没有 membership field 。

关于python - Django使用 'through'关系表从模型中获取所有相关对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41598801/

相关文章:

python - Python 3.5 类型提示是否允许协变返回类型?

Django:过滤多对多字段时重复

python - 在 Python 中使用库对元组进行分组

Django session cookie 过期日期

python - Django 原始 SQL 查询与外键

Django:用于 MongoDB 的长字段 (BigIntegerField)

Django - 使用外键关系同时保存两条记录

python - django 一次重写删除级联

python - 在非标准位置构建支持 SSL 的 Python

python - 如何实现@property