views:

29

answers:

2

Here's a simple relational pair of models.

class Shelf(models.Model):
  name = models.CharField(max_length=100)

  def has_books(self):
    if Book.objects.filter(shelf=self):
      return True
    else:
      return False

class Book(models.Model):
  shelf = models.ForeignKey(Shelf)
  name = models.CharField(max_length=100)

Is there a better (or alternative) way to write the "has_book" method?

I'm not a fan of the double database hit but I want to do this at the model level.

+3  A: 

You can do:

def has_books(self):
    return self.book_set.all().count() > 0
Hassan
I guess I'm looking for more a fancy "Django-y" way to handle cross-model checking...
Brant
What do you mean? This is a "Django-y" way and optimal as you should only query for count. +1
Béres Botond
Yea, "Django-y" is a poor term... I suppose I was trying to find some django API method that would allow me to get it done in a single hit.
Brant
I actually read your code wrong the first time I commented... the _set is exactly what I was looking for.
Brant
+1  A: 

I'm not sure what your objection is to the way Hassan has written it, but perhaps - based on your 'double database hit' comment - you're looking for a way of checking all Shelf instances at once? If so, you can do it with annotations:

from django.db.models import Count
Book.objects.all().annotate(num_books=Count('book')).filter(num_books__gt=0)

This gives you a list of all shelves with at least one book.

Daniel Roseman
I don't really have a problem with it. It was more of an exploratory question... I was just wondering if there _was_ a way to get it done in a single hit. Thanks.
Brant