Reputation: 211
let's assume, I have a model called Chicken:
class Chicken(models.Model):
name = models.CharField(max_length=30)
and I also have a model called Egg that has a ForeignKey to the Chicken-model:
class Egg(models.Model):
chicken = models.ForeignKey(Chicken)
layed_on = models.DateField(auto_add_now=True)
Now I want to create a view that contains a list of the all the chickens and the date when they layed their last egg.
I know how to get all eggs layed by a chicken, using something like this:
c = Chicken.objects.get(name='Henry')
e = c.egg_set.all()
But that doesn't really help, because I have a lot of chickens and I want to only get the date of their latest egg. I also don't know how to get that egg information into my view for easy access. In my view I would like to do something like this:
{% for chicken in chickens %}
<p>{{ chicken.name }} layed is last egg on {{ chicken.last_egg }}</p>
{% endfor %}
This is probably a very basic question, but I'm just a beginner and I would greatly appreciate any help you can give. The Django documentation does not really help me in this case.
Upvotes: 1
Views: 178
Reputation: 1382
I personally like to solve such a problem annotating methods in my models with the @property annotation.
An example: In your Chicken model, you would have a method like:
@property
def last_egg(self):
return self.egg_set.order_by('-layed_on')[0]
And in your template, you could use it as a regular model field.
{{my_chicken.last_egg}}
I would additionally like to know if there are any issues about this solution, and what you guys think about it. Maybe we could make this question a nice talk about how to ellegantly solve this issue.
Hope it helps.
Upvotes: 0
Reputation: 1144
What you're looking for is django's annotation feature. Basically, you want to annotate each row in chicken with the Max
of egg's layed_on field. Without a prompt right in front of me, I can't guarentee the exact statement below, but it should give you a starting point.
Edit your chicken model like this:
class Egg(models.Model):
chicken = models.ForeignKey(Chicken, related_name='eggs')
layed_on = models.DateField(auto_add_now=True)
from django.db.models import Max
Chicken.objects.annotate(last_egg=Max('eggs__layed_on'))
Upvotes: 4