From 64c47856dd0de95e2d425012af1542f4d2428824 Mon Sep 17 00:00:00 2001 From: Ned Batchelder <ned@edx.org> Date: Thu, 16 May 2019 09:13:59 -0400 Subject: [PATCH] DRF 3.7.4 changed how you delegate to another view, so don't The error in the test was: ``` AssertionError: The `request` argument must be an instance of `django.http.HttpRequest`, not `rest_framework.request.Request`. ``` The (controversial) incompatible change was in 3.7.4: https://github.com/encode/django-rest-framework/pull/5618 I'll look into whether there's another way to address it. <details> <summary>Full error report</summary> ``` AssertionError: The `request` argument must be an instance of `django.http.HttpRequest`, not `rest_framework.request.Request`. Stacktrace self = <lms.djangoapps.discussion_api.tests.test_views.CommentViewSetListTest testMethod=test_profile_image_request_for_null_endorsed_by> def test_profile_image_request_for_null_endorsed_by(self): """ Tests if 'endorsed' is True but 'endorsed_by' is null, the api does not crash. This is the case for some old/stale data in prod/stage environments. """ self.register_get_user_response(self.user) thread = self.make_minimal_cs_thread({ "thread_type": "question", "endorsed_responses": [make_minimal_cs_comment({ "id": "endorsed_comment", "user_id": self.user.id, "username": self.user.username, "endorsed": True, })], "non_endorsed_resp_total": 0, }) self.register_get_thread_response(thread) self.create_profile_image(self.user, get_profile_image_storage()) response = self.client.get(self.url, { "thread_id": thread["id"], "endorsed": True, > "requested_fields": "profile_image", }) lms/djangoapps/discussion_api/tests/test_views.py:1446: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/test.py:291: in get response = super(APIClient, self).get(path, data=data, **extra) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/test.py:208: in get return self.generic('GET', path, **r) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/test.py:237: in generic method, path, data, content_type, secure, **extra) ../venvs/edxapp/local/lib/python2.7/site-packages/django/test/client.py:416: in generic return self.request(**r) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/test.py:288: in request return super(APIClient, self).request(**kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/test.py:240: in request request = super(APIRequestFactory, self).request(**kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/django/test/client.py:501: in request six.reraise(*exc_info) ../venvs/edxapp/local/lib/python2.7/site-packages/django/core/handlers/exception.py:41: in inner response = get_response(request) ../venvs/edxapp/local/lib/python2.7/site-packages/django/core/handlers/base.py:249: in _legacy_get_response response = self._get_response(request) ../venvs/edxapp/local/lib/python2.7/site-packages/django/core/handlers/base.py:187: in _get_response response = self.process_exception_by_middleware(e, request) ../venvs/edxapp/local/lib/python2.7/site-packages/django/core/handlers/base.py:185: in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/django/utils/decorators.py:185: in inner return func(*args, **kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/django/views/decorators/csrf.py:58: in wrapped_view return view_func(*args, **kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/viewsets.py:95: in view return self.dispatch(request, *args, **kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/views.py:494: in dispatch response = self.handle_exception(exc) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/views.py:491: in dispatch response = handler(request, *args, **kwargs) lms/djangoapps/discussion_api/views.py:505: in list form.cleaned_data["requested_fields"], lms/djangoapps/discussion_api/api.py:659: in get_comment_list results = _serialize_discussion_entities(request, context, responses, requested_fields, DiscussionEntity.comment) lms/djangoapps/discussion_api/api.py:468: in _serialize_discussion_entities request, results, usernames, discussion_entity_type, include_profile_image lms/djangoapps/discussion_api/api.py:413: in _add_additional_response_fields username_profile_dict = _get_user_profile_dict(request, usernames=','.join(usernames)) lms/djangoapps/discussion_api/api.py:350: in _get_user_profile_dict user_profile_details = AccountViewSet.as_view({'get': 'list'})(request).data ../venvs/edxapp/local/lib/python2.7/site-packages/django/views/decorators/csrf.py:58: in wrapped_view return view_func(*args, **kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/viewsets.py:95: in view return self.dispatch(request, *args, **kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/views.py:477: in dispatch request = self.initialize_request(request, *args, **kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/viewsets.py:118: in initialize_request request = super(ViewSetMixin, self).initialize_request(request, *args, **kwargs) ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/views.py:381: in initialize_request parser_context=parser_context _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <rest_framework.request.Request object at 0x7f597c773890> request = <rest_framework.request.Request object at 0x7f597fa20f90> parsers = [<openedx.core.lib.api.parsers.MergePatchParser object at 0x7f59810c32d0>] authenticators = [<edx_rest_framework_extensions.auth.jwt.authentication.JwtAuthentication object at 0x7f597c713690>, <openedx.core.lib...rest_framework_extensions.auth.session.authentication.SessionAuthenticationAllowInactiveUser object at 0x7f597c773390>] negotiator = <rest_framework.negotiation.DefaultContentNegotiation object at 0x7f597fa20410> parser_context = {'args': (), 'kwargs': {}, 'view': <openedx.core.djangoapps.user_api.accounts.views.AccountViewSet object at 0x7f597c7846d0>} def __init__(self, request, parsers=None, authenticators=None, negotiator=None, parser_context=None): assert isinstance(request, HttpRequest), ( 'The `request` argument must be an instance of ' '`django.http.HttpRequest`, not `{}.{}`.' > .format(request.__class__.__module__, request.__class__.__name__) ) E AssertionError: The `request` argument must be an instance of `django.http.HttpRequest`, not `rest_framework.request.Request`. ../venvs/edxapp/local/lib/python2.7/site-packages/rest_framework/request.py:159: AssertionError ``` </details> --- lms/djangoapps/discussion/rest_api/api.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lms/djangoapps/discussion/rest_api/api.py b/lms/djangoapps/discussion/rest_api/api.py index 27b9bdc04ec..1b7a9aa8709 100644 --- a/lms/djangoapps/discussion/rest_api/api.py +++ b/lms/djangoapps/discussion/rest_api/api.py @@ -61,6 +61,7 @@ from openedx.core.djangoapps.django_comment_common.signals import ( thread_voted ) from openedx.core.djangoapps.django_comment_common.utils import get_course_discussion_settings +from openedx.core.djangoapps.user_api.accounts.api import get_account_settings from openedx.core.djangoapps.user_api.accounts.views import AccountViewSet from openedx.core.lib.exceptions import CourseNotFoundError, DiscussionNotFoundError, PageNotFoundError @@ -365,10 +366,11 @@ def _get_user_profile_dict(request, usernames): A dict with username as key and user profile details as value. """ - request.GET = request.GET.copy() # Make a mutable copy of the GET parameters. - request.GET['username'] = usernames - user_profile_details = AccountViewSet.as_view({'get': 'list'})(request).data - + if usernames: + username_list = usernames.split(",") + else: + username_list = [] + user_profile_details = get_account_settings(request, username_list) return {user['username']: user for user in user_profile_details} -- GitLab