views:

29

answers:

3

Given the simplified example below, how would I access my custom "current_status" property within a queryset? Is it even possible?

At the moment, I want to list the all the current Events and show the current status. I can get the property to display in a template ok, but I can't order the queryset by it. Alternatively, would I need to create a custom manager with some kind of nested "if" statement in the 'Select'?

class Event(models.Model):
    ....

    date_registered = models.DateField(null=True, blank=True)
    date_accepted = models.DateField(null=True, blank=True)
    date_reported = models.DateField(null=True, blank=True)
    ...

    def _get_current_status(self):
        ...
        if self.date_reported:
            return "Reported"
        if self.date_accepted:
            return "Accepted"
        if self.date_registered:
            return "Registered"
        if self.date_drafted:
            return "Drafted"

    current_status = property(_get_current_status)
A: 

You cannot use a custom property in query, since Django's ORM will try to map it to a database column and fail. Of course you can use it in an evaluated queryset, e.g. when you're iterating about the objects of a query's results!
You can only filter for things like: Event.objects.filter(date_drafted__isnull=False). http://docs.djangoproject.com/en/dev/ref/models/querysets/#isnull

lazerscience
+1  A: 

Instead of calculating the status as a property, create a proper model field for it and update it in the save method. Then you can use that field directly in the query.

Daniel Roseman
A: 

Thanks to Daniel. I think that I might use your approach. However, I also managed to get it working using the queryset 'extra' method, which might also be useful to other people, although its probably isn't database agnostic.

qs = Event.objects.extra(select={'current_status_id': 
            '''(CASE 
            WHEN date_cancelled THEN 0
            WHEN date_closed THEN 6
            WHEN date_signed_off THEN 5
            WHEN date_reported THEN 4
            WHEN date_accepted THEN 3
            WHEN date_registered THEN 2
            WHEN date_drafted THEN 1
            ELSE 99
            END)
            '''})
alj