【问题标题】:Django M2M with "self" through int. table, how to get related items通过 int 带有“self”的 Django M2M。表,如何获取相关项目
【发布时间】:2011-08-16 06:12:12
【问题描述】:

我正在尝试在我的一个模型中建立一些 M2M 关系。 Django让我把related_name参数放到一些字段中,我把它们放进去。但是,我现在对如何获取相关项目感到困惑。这是我简化的模型。

class Post(models.Model):
    # other fields
    relevancy = models.ManyToManyField("self",through="Traffic",symmetrical=False,related_name="relevant",blank=True)

    #some method definitions

class Traffic(models.Model):
    tfrom = models.ForeignKey(Post,related_name="tfrom")
    tto = models.ForeignKey(Post,related_name="tto")
    count = models.PositiveIntegerField(default=0)

这是一个分析用户趋势,并给其他用户提供建议的工具。我感到困惑的部分是我获得与相关帖子相关的帖子的部分。例如,当我选择发布时,我如何获得从该帖子获得流量的一组帖子,或从该帖子获得流量的一组帖子等。这是我之前发布的related question

PS:英语不是我的主要语言,如果我的问题难以理解,请见谅。

【问题讨论】:

    标签: django many-to-many


    【解决方案1】:

    这取决于中间模型定义。中间模型的第一个 FK 定义了“主体”访问,所以

    a_post.relevancy.all()
    

    是所有Post 实例的集合,其流量a_post 到它们

    a_post.relevant.all()
    

    是所有Post 实例的集合,其流量从它们到a_post

    您真的应该考虑一下您的命名约定,这很令人困惑。

    links = models.ManyToManyField("self",
                 through="Traffic",
                 symmetrical=False,
                 related_name="referrers",
                 blank=True)
    

    关键在django源代码中:

    https://code.djangoproject.com/browser/django/trunk/django/db/models/fields/related.py#L1059

                        # If this is an m2m-intermediate to self,
                        # the first foreign key you find will be
                        # the source column. Keep searching for
                        # the second foreign key.
    

    所以你有这个

    s1 = set(my_post.relevancy.all())
    s2 = set(t.tto for t in my_post.tfrom.select_related('tto'))
    assert not s1.symmetric_difference(s2)
    

    在更简单的 SQL 中,描述符 p.relevancy 获取 ID 所在的所有 Post 实例

    select traffic.tto_id where traffic.tfrom_id = my_post_id
    

    【讨论】:

    • 首先,您是指定义字段的顺序,还是其他?例如,如果我先定义 tto,然后再定义 tfrom,会有什么不同吗?
    • 没错。字段在模型初始化时被检索,并存储在模型的 Meta 类中的字段列表中(不要与元类混淆,这是另一回事),然后实例上的属性是使用字段获取数据的“描述符” .在任何情况下,为事物加上相关名称将有助于检测此类问题,因此在所有情况下,您都可以检查是否为事物定义了正确的名称。
    猜你喜欢
    • 2014-12-28
    • 2012-02-29
    • 1970-01-01
    • 2014-12-21
    • 1970-01-01
    • 2021-04-21
    • 2019-08-09
    • 2016-05-07
    • 2016-09-28
    相关资源
    最近更新 更多