Django 数据库关系 - 多对多、一对多

0 投票
1 回答
542 浏览
提问于 2025-04-17 14:52

我在理解Django中的多对一和多对多关系时,总是感到有些困惑。我知道它们在SQL和数据库中的工作原理,也明白外键的概念,但有些地方还是不太明白。

在多对多关系中,双方都可以自动访问对方,就像是一个“反向”的一对多关系。但是,我还是无法从概念上完全理解这一点。

多对一的例子:

class Reporter(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.EmailField()

    def __unicode__(self):
        return u"%s %s" % (self.first_name, self.last_name)

class Article(models.Model):
    headline = models.CharField(max_length=100)
    pub_date = models.DateField()
    reporter = models.ForeignKey(Reporter)

    def __unicode__(self):
        return self.headline

    class Meta:
        ordering = (’headline’,)

我可以这样做:

>>> r = Reporter(first_name=’John’, last_name=’Smith’, email=’john@example.com’)
>>> r.save()
>>> a = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter=r)
>>> a.save()
>>> a.reporter
<Reporter: John Smith>

所以,我可以通过外键从文章类访问记者类。

多对多的例子:

class Publication(models.Model):
    title = models.CharField(max_length=30)

    def __unicode__(self):
        return self.title

    class Meta:
        ordering = (’title’,)

class Article(models.Model):
    headline = models.CharField(max_length=100)
    publications = models.ManyToManyField(Publication)

    def __unicode__(self):
        return self.headline

    class Meta:
        ordering = (’headline’,)

我的问题是——我可以通过文章类上的ManyToManyField访问出版物类,就像我在多对一的例子中那样。那么,多对多和多对一有什么不同呢?我还能用多对多做些什么?(当然,我也可以在两者之间进行反向访问,但我现在想暂时忽略反向关系,以免让我更困惑。)

为了更好地表达我的问题,通常在多对多关系中还能做些什么,而在多对一关系中又做不到呢?

声明一下——我刚开始学习编程,已经读过Django官方文档中关于模型的整整100页,所以请不要再把我引导回去。如果可以的话,我已经在从中学习了。

另外,我对代码的理解更好,所以如果可以的话,请包含一些代码示例。

1 个回答

1

一个记者可以写很多文章,但一篇文章只能有一个记者。

# This will get the reporter of an article
article.reporter
# This will get all the articles of a reporter
reporter.article_set.all()
# You cannot add another reporter to an article
article.reporter.add(r) # This will raise an Error!

另一方面,

一篇文章可以有很多出版物,而一份出版物也可以与很多文章有关联。

# This will get all the publications of an article
article.publications.all()
# This will get all the related articles of a publication
publication.article_set.all()
# You CAN add another publication to an article
article.publications.add(p) # No Error here

撰写回答