Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django @property calculating a model field: FieldError: Cannot resolve keyword

Tags:

python

django

I'm following the method used by @Yauhen Yakimovich in this question:

do properties work on django model fields?

To have a model field that is a calculation of a different model.

The Problem:

FieldError: Cannot resolve keyword 'rating' into field. Choices are: _rating

The rating model field inst correctly hidden and overridden by my rating property causing an error when I try to access it.

My model:

class Restaurant(models.Model):    
    ...
    ...
    @property
    def rating(self):
        from django.db.models import Avg
        return Review.objects.filter(restaurant=self.id).aggregate(Avg('rating'))['rating__avg']

Model in Yauhen's answer:

class MyModel(models.Model):
    __foo = models.CharField(max_length = 20, db_column='foo')
    bar = models.CharField(max_length = 20)

    @property
    def foo(self):
        if self.bar:
            return self.bar
        else:
            return self.__foo

    @foo.setter
    def foo(self, value):
        self.__foo = value

Any ideas on how to correctly hid the rating field and define the @property technique?

like image 531
agconti Avatar asked Aug 26 '13 15:08

agconti


2 Answers

Solved by using sorted()

I was using a query with order_by() to call rating. order_by() is at the database level and doesnt know about my property. Soultion, use Python to sort instead:

sorted(Restaurant.objects.filter(category=category[0]), key=lambda x: x.rating, reverse=True)[:5]

If you encounter a similar error check through your views for anything that might be calling the property. Properties will no longer work at the datatbase level.

like image 65
agconti Avatar answered Sep 18 '22 01:09

agconti


Change this line:

self._rating = Review.objects.filter(restaurant=self.id).aggregate(Avg('rating'))['rating__avg']

into this one:

self._rating = Review.objects.filter(restaurant=self.id).aggregate(Avg('_rating'))['_rating__avg']

(notice change of reference in query from rating and rating__avg to _rating and _rating__avg)

like image 44
Tadeck Avatar answered Sep 18 '22 01:09

Tadeck