views:

342

answers:

2

Hello. I have the following classes in my models file

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

I'd like to do a count on the number of Subscriptions on a particular HardwareNode and display that on the admin section for the HardwareNode class e.g. 10 subscriptions hosted on node 2.

I'm still learning Django and I'm not sure where I would accomplish this. Can/should I do it in the models.py or in the HTML?

Thanks,

-seth

A: 

In your HardwareNode class keep a list of Subscriptions, and then either create a function that returns the length of that list or just access the variable's length through the HTML. This would be better than going through all of your subscriptions and counting the number of HardwareNodes, especially since Django makes it easy to have a bi-directional relationship in the database.

AlbertoPL
+3  A: 

When creating a foreign_key, the other model gets a manager that returns all instances of the first model (see navigating backward) In your case, it would be named "subscription_set".

In addition, Django allows for virtual fields in models, called "Model Methods", that are not connected to database data, but are implemented as methods of the model (see model methods)

Putting all together, you can have something like this:

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())

And then, include subscription_count in the list of fields to be listed in the admin panel.

Note: as usual, I did not check this code, and it may even not run as it is, but it should give some idea on how to work on your problem; moreover, I have used a lambda just for brevity but usually I think it would be a better option (style, maintenability, etc.) to use a named one.

Roberto Liffredo
This won't work, as self.subscription_set is a method and doesn't have a length. Plus, you should never use len() on querysets as that forces evaluation. Use self.subscription_set.count() instead.
Daniel Roseman
any reason for using lambda rather than a named function?
John Montgomery
Thanks Daniel, I knew I was forgetting something :-) (now it should be correct). There are no real reasons for using a lambda - just brevity in the example. I have updated the notes, to somehow discourage its usage.
Roberto Liffredo