在Django中显示来自另一个表的行数

2 投票
2 回答
2551 浏览
提问于 2025-04-15 12:30

我在我的模型文件里有以下这些类:

class HardwareNode(models.Model):
    ip_address = models.CharField(max_length=15)
    port = models.IntegerField()
    location = models.CharField(max_length=50)
    hostname = models.CharField(max_length=30)

    def __unicode__(self):
        return self.hostname

class Subscription(models.Model):
    customer = models.ForeignKey(Customer)
    package = models.ForeignKey(Package)
    location = models.ForeignKey(HardwareNode)
    renewal_date = models.DateTimeField('renewal date')

    def __unicode__(self):
        x = '%s %s' % (self.customer.hostname, str(self.package))
        return x

我想统计一下某个硬件节点上的订阅数量,并在硬件节点类的管理界面上显示出来,比如说“节点2上有10个订阅”。

我还在学习Django,不太确定该怎么做。这个统计应该在models.py里做,还是在HTML里做呢?

谢谢,

-seth

2 个回答

0

在你的HardwareNode类里面,保持一个Subscriptions的列表。然后你可以创建一个函数来返回这个列表的长度,或者直接通过HTML访问这个变量的长度。这样做比逐个检查所有的订阅并计算HardwareNode的数量要好得多,特别是因为Django让你在数据库中建立双向关系变得很简单。

7

当你创建一个 foreign_key(外键)时,另一个模型会获得一个管理器,这个管理器可以返回第一个模型的所有实例(你可以查看如何向后导航)。在你的情况下,这个管理器会被命名为 "subscription_set"。

另外,Django 还允许在模型中创建虚拟字段,这些字段叫做“模型方法”,它们并不直接连接到数据库的数据,而是作为模型的方法来实现(你可以查看模型方法)。

把这些结合起来,你可以得到类似这样的代码:

class HardwareNode(models.Model):
    ip_address = models.CharField(max_length=15)
    port = models.IntegerField()
    location = models.CharField(max_length=50)
    hostname = models.CharField(max_length=30)
    subscription_count = lambda(self: self.subscription_set.count())

然后,把 subscription_count 加入到要在管理面板中显示的字段列表里。

注意:像往常一样,我没有检查这段代码,它可能甚至无法直接运行,但它应该能给你一些关于如何解决你问题的思路;此外,我使用了一个 lambda 表达式只是为了简洁,但通常我认为使用命名的函数会是更好的选择(在风格、可维护性等方面)。

撰写回答