1

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
2
  • EDIT: It's worth noting that my ultimate solution was to use queryset.extra() instead of annotate. There seems to be some sort of bug with django rest framework v2.4.5 that raises the error and doesn't fetch the annotate fields during serialization. That is my thought at least. I'll have to further investigate this. Commented Jul 7, 2015 at 19:47
  • try this link: working very fine: stackoverflow.com/questions/31920853/… Commented Jul 14, 2017 at 2:12

1 Answer 1

1

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)]
    )
Sign up to request clarification or add additional context in comments.

6 Comments

Apologies I copied in my model wrong, see my edit above, it is still receiving that error. Thank you
Thank you, please see the stack trace above
what is your error again ?? "Cannot resolve keyword 'widget_count' into field. Choices are: description, id, name, review" or the one in Traceback?
review_count. If I only return the queryset in construct_queryset I get no errors. But when i perform queryset.annotate, it returns the traceback ex: if I just do return queryset it works fine
can you once try Widget.objects.annotate(review_count=Count('review')).order_by('-review_count') , and see if helps!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.