Reputation: 172
I am trying to construct a queryset dynamically using model method but in doing so I am receiving this error in django rest framework v2.4.5 and django 1.7.8:
Cannot resolve keyword 'review_count' into field. Choices are: description, id, name, review
I'm unable to display the queryset created by the construct_queryset
method in my viewset, although it works fine in the django admin. I believe it has something to do with the way that django rest framework is instantiating the models. I am not entirely sure what might be causing this issue, any help would be appreciated, thank you.
I upgraded to django 1.8 but it's not supported by django rest framework v2.4.5 and I cannot upgrade to v3 at this time unfortunately.
models.py:
class Widget (models.Model):
name = models.CharField(max_length=255)
description = models.CharField(max_length=255)
class Review (models.Model):
name = models.CharField(max_length=255)
rating = models.IntegerField(
validators=[MinValueValidator(1), MaxValueValidator(5)]
)
widget = models.ForeignKey(Widget)
class WidgetQS(models.Model):
""" A model used for constructing a dynamic queryset """
ORDER_CHOICES = (
('annotate_review', 'order by review count'),
...
)
order_by_field = models.CharField(max_length=255, choices=ORDER_CHOICES)
def construct_queryset(self, user=None):
queryset = Widget.objects.all()
if self.order_by_field == 'annotate_review':
result_qs = queryset.annotate(
review_count=Count('review')
).order_by('-review_count')
return result_qs
serializers.py:
class WidgetSerializer (serializers.HyperlinkedModelSerializer):
objects = serializers.SerializerMethodField('get_objects')
def get_objects(self, obj):
request = self.context.get('request', None)
if request:
try:
user = request.user
except:
user = None
qs = obj.construct_queryset(user=user)
if qs:
return qs.values_list('id', flat=True)
return []
views.py
class WidgetViewSet (ModelViewSet):
serializer_class = WidgetQSSerializer
queryset = WidgetQS.objects.all()
Stack Trace
Environment:
Request Method: GET
Request URL: http://localhost:8080/api/widgetqs
Django Version: 1.7.8
Python Version: 2.7.6
Installed Applications:
(u'grappelli',
u'django.contrib.admin',
u'django.contrib.auth',
u'django.contrib.contenttypes',
u'django.contrib.sessions',
u'django.contrib.messages',
u'django.contrib.staticfiles',
u'django.contrib.humanize',
u'corsheaders',
u'rest_framework',
u'social.apps.django_app.default',
u'widget',
u'debug_toolbar')
Installed Middleware:
(u'django.contrib.sessions.middleware.SessionMiddleware',
u'django.middleware.common.CommonMiddleware',
u'django.middleware.csrf.CsrfViewMiddleware',
u'django.contrib.auth.middleware.AuthenticationMiddleware',
u'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
u'django.contrib.messages.middleware.MessageMiddleware',
u'django.middleware.clickjacking.XFrameOptionsMiddleware',
u'social.apps.django_app.middleware.SocialAuthExceptionMiddleware',
u'bugsnag.django.middleware.BugsnagMiddleware',
u'debug_toolbar.middleware.DebugToolbarMiddleware')
Traceback:
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
111. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
57. return view_func(*args, **kwargs)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/viewsets.py" in view
79. return self.dispatch(request, *args, **kwargs)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
403. response = self.handle_exception(exc)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
400. response = handler(request, *args, **kwargs)
File "/Users/nabil/Documents/projects/widget_project/widget_project/timestamp/mixins.py" in list
108. return Response(serializer.data)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/serializers.py" in data
576. self._data = self.to_native(obj)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/serializers.py" in to_native
355. value = field.field_to_native(obj, field_name)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/serializers.py" in field_to_native
414. return [self.to_native(item) for item in value.all()]
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/serializers.py" in to_native
355. value = field.field_to_native(obj, field_name)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/fields.py" in field_to_native
1043. return self.to_native(value)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/rest_framework/fields.py" in to_native
225. return [self.to_native(item) for item in value]
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/query.py" in __iter__
141. self._fetch_all()
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/query.py" in _fetch_all
966. self._result_cache = list(self.iterator())
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/query.py" in iterator
1202. for row in self.query.get_compiler(self.db).results_iter():
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in results_iter
701. for rows in self.execute_sql(MULTI):
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
776. sql, params = self.as_sql()
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in as_sql
102. ordering, o_params, ordering_group_by = self.get_ordering()
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in get_ordering
430. self.query.get_meta(), default_order=asc):
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in find_ordering_name
466. field, targets, alias, joins, path, opts = self._setup_joins(pieces, opts, alias)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in _setup_joins
499. pieces, opts, alias)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/query.py" in setup_joins
1463. names, opts, allow_many, fail_on_missing=True)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/query.py" in names_to_path
1427. self.raise_field_error(opts, name)
File "/Users/nabil/.virtualenvs/widget_project/lib/python2.7/site-packages/django/db/models/sql/query.py" in raise_field_error
1433. "Choices are: %s" % (name, ", ".join(available)))
Exception Type: FieldError at /api/widgetqs
Exception Value: Cannot resolve keyword 'review_count' into field. Choices are: description, id, name, review
Upvotes: 1
Views: 604
Reputation: 1285
As you can see in your function :
def construct_queryset(self, user=None):
queryset = Widget.objects.all()
if self.order_by_field == 'annotate_review':
result_qs = queryset.annotate(
review_count=Count('review')
).order_by('-review_count')
return result_qs
Your queryset is
Widget.objects.all()
and you are trying to annotate a field which has no relation with your Review model.
If you want this to work, you have to add a foreignkey to your model Review for Model Widget like this :
class Widget (models.Model):
name = models.CharField(max_length=255)
description = models.CharField(max_length=255)
class Review (models.Model):
widget = models.ForeignKey(Widget)
name = models.CharField(max_length=255)
rating = models.IntegerField(
validators=[MinValueValidator(1), MaxValueValidator(5)]
)
Upvotes: 1