Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Django custom model method property in order_by()

I'm currently learning Django and some of my models have custom methods to get values formatted in a specific way. Is it possible to use the value of one of these custom methods that I've defined as a property in a model with order_by()?

Here is an example that demonstrates how the property is implemented.

class Author(models.Model):     first_name = models.CharField(max_length=30)     last_name = models.CharField(max_length=40)     email = models.EmailField(blank=True, verbose_name='e-mail')      def _get_full_name(self):         return u'%s %s' % (self.first_name, self.last_name)     full_name = property(_get_full_name)      def __unicode__(self):         return self.full_name 

With this model I can do:

>>> Author.objects.all() [<Author: John Doh>, <Author: Jane Doh>, <Author: Andre Miller>] >>> Author.objects.order_by('first_name') [<Author: Andre Miller>, <Author: Jane Doh>, <Author: John Doh>] 

But I cannot do:

>>> Author.objects.order_by('full_name') FieldError: Cannot resolve keyword 'full_name' into field. Choices are: book, email, first_name, id, last_name 

What would be the correct way to use order_by on a custom property like this?

like image 713
Andre Miller Avatar asked Jun 11 '09 14:06

Andre Miller


People also ask

What is a field class in Django?

It’s important to realize that a Django field class is not what is stored in your model attributes. The model attributes contain normal Python objects. The field classes you define in a model are actually stored in the Meta class when the model class is created (the precise details of how this is done are unimportant here).

Can we use @property decorator to access model methods as attributes?

Since this is a method that's called like a traditional function with arguments. While using the @property decorator can make it a bit more convenient to access model methods as attributes, you can't filter querysets by them, use them for ordering, or any other operation that happens at the database level.

What is a model field in Python?

If you break it down, a model field provides a way to take a normal Python object – string, boolean, datetime, or something more complex like Hand – and convert it to and from a format that is useful when dealing with the database.


1 Answers

No, you can't do that. order_by is applied at the database level, but the database can't know anything about your custom Python methods.

You can either use the separate fields to order:

Author.objects.order_by('first_name', 'last_name') 

or do the ordering in Python:

sorted(Author.objects.all(), key=lambda a: a.full_name) 
like image 119
Daniel Roseman Avatar answered Oct 03 '22 17:10

Daniel Roseman