Commit 14edb1b5 by Renzo Lucioni

Upgrade to DRF 3.6.3

3.6.3 is tested against Django 1.11 and includes built-in, interactive API documentation. Sadly, the built-in documentation struggles with the URL patterns in this project and is only able to construct top-level entries (i.e., api, extensions, publisher). All the endpoints that should be underneath those are missing. This issue is documented in https://github.com/encode/django-rest-framework/issues/4984. Until it's resolved, we'll continue using django-rest-swagger.

The 3.6 release announcement is at http://www.django-rest-framework.org/topics/3.6-announcement. Extended release notes are at http://www.django-rest-framework.org/topics/release-notes/#36x-series.

LEARNER-1590
parent daf77fa9
import ddt import ddt
import mock import mock
from django.test import TestCase from django.test import TestCase
from rest_framework.request import Request
from rest_framework.test import APIRequestFactory
from course_discovery.apps.api.utils import cast2int from course_discovery.apps.api.utils import cast2int, get_query_param
LOGGER_PATH = 'course_discovery.apps.api.utils.logger.exception' LOGGER_PATH = 'course_discovery.apps.api.utils.logger.exception'
...@@ -27,3 +29,14 @@ class Cast2IntTests(TestCase): ...@@ -27,3 +29,14 @@ class Cast2IntTests(TestCase):
cast2int(value, self.name) cast2int(value, self.name)
self.assertTrue(mock_logger.called) self.assertTrue(mock_logger.called)
class TestGetQueryParam:
def test_with_request(self):
factory = APIRequestFactory()
request = Request(factory.get('/?q=1'))
assert get_query_param(request, 'q') == 1
def test_without_request(self):
assert get_query_param(None, 'q') is None
...@@ -26,3 +26,15 @@ def cast2int(value, name): ...@@ -26,3 +26,15 @@ def cast2int(value, name):
except ValueError: except ValueError:
logger.exception('The "%s" parameter requires an integer value. "%s" is invalid.', name, value) logger.exception('The "%s" parameter requires an integer value. "%s" is invalid.', name, value)
raise raise
def get_query_param(request, name):
"""
Get a query parameter and cast it to an integer.
"""
# This facilitates DRF's schema generation. For more, see
# https://github.com/encode/django-rest-framework/blob/3.6.3/rest_framework/schemas.py#L383
if request is None:
return
return cast2int(request.query_params.get(name), name)
import logging
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from course_discovery.apps.api import serializers from course_discovery.apps.api import serializers
from course_discovery.apps.api.exceptions import InvalidPartnerError from course_discovery.apps.api.exceptions import InvalidPartnerError
from course_discovery.apps.api.utils import cast2int
from course_discovery.apps.core.models import Partner from course_discovery.apps.core.models import Partner
logger = logging.getLogger(__name__)
User = get_user_model() User = get_user_model()
def get_query_param(request, name):
"""
Get a query parameter and cast it to an integer.
"""
return cast2int(request.query_params.get(name), name)
def prefetch_related_objects_for_courses(queryset): def prefetch_related_objects_for_courses(queryset):
""" """
Pre-fetches the related objects that will be serialized with a `Course`. Pre-fetches the related objects that will be serialized with a `Course`.
......
...@@ -8,7 +8,8 @@ from rest_framework.response import Response ...@@ -8,7 +8,8 @@ from rest_framework.response import Response
from course_discovery.apps.api import filters, serializers from course_discovery.apps.api import filters, serializers
from course_discovery.apps.api.pagination import ProxiedPagination from course_discovery.apps.api.pagination import ProxiedPagination
from course_discovery.apps.api.v1.views import PartnerMixin, get_query_param from course_discovery.apps.api.utils import get_query_param
from course_discovery.apps.api.v1.views import PartnerMixin
from course_discovery.apps.core.utils import SearchQuerySetWrapper from course_discovery.apps.core.utils import SearchQuerySetWrapper
from course_discovery.apps.course_metadata.constants import COURSE_RUN_ID_REGEX from course_discovery.apps.course_metadata.constants import COURSE_RUN_ID_REGEX
from course_discovery.apps.course_metadata.models import CourseRun from course_discovery.apps.course_metadata.models import CourseRun
......
...@@ -5,7 +5,7 @@ from rest_framework.permissions import IsAuthenticated ...@@ -5,7 +5,7 @@ from rest_framework.permissions import IsAuthenticated
from course_discovery.apps.api import filters, serializers from course_discovery.apps.api import filters, serializers
from course_discovery.apps.api.pagination import ProxiedPagination from course_discovery.apps.api.pagination import ProxiedPagination
from course_discovery.apps.api.v1.views import get_query_param from course_discovery.apps.api.utils import get_query_param
from course_discovery.apps.course_metadata.choices import CourseRunStatus from course_discovery.apps.course_metadata.choices import CourseRunStatus
from course_discovery.apps.course_metadata.constants import COURSE_ID_REGEX from course_discovery.apps.course_metadata.constants import COURSE_ID_REGEX
from course_discovery.apps.course_metadata.models import Course, CourseRun from course_discovery.apps.course_metadata.models import Course, CourseRun
......
...@@ -6,7 +6,7 @@ from rest_framework_extensions.cache.mixins import CacheResponseMixin ...@@ -6,7 +6,7 @@ from rest_framework_extensions.cache.mixins import CacheResponseMixin
from course_discovery.apps.api import filters, serializers from course_discovery.apps.api import filters, serializers
from course_discovery.apps.api.pagination import ProxiedPagination from course_discovery.apps.api.pagination import ProxiedPagination
from course_discovery.apps.api.v1.views import get_query_param from course_discovery.apps.api.utils import get_query_param
from course_discovery.apps.course_metadata.models import Program from course_discovery.apps.course_metadata.models import Program
......
...@@ -8,4 +8,3 @@ class CommentSerializer(serializers.ModelSerializer): ...@@ -8,4 +8,3 @@ class CommentSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Comments model = Comments
fields = ('comment', 'modified', ) fields = ('comment', 'modified', )
readonly_fields = ('modified', )
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-21 13:39+0500\n" "POT-Creation-Date: 2017-07-13 17:02-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: apps/api/filters.py #: apps/api/filters.py
#, python-brace-format #, python-brace-format
...@@ -305,7 +305,7 @@ msgstr "" ...@@ -305,7 +305,7 @@ msgstr ""
msgid "Course number format e.g CS002x, BIO1.1x, BIO1.2x" msgid "Course number format e.g CS002x, BIO1.1x, BIO1.2x"
msgstr "" msgstr ""
#: apps/course_metadata/models.py #: apps/course_metadata/models.py apps/publisher/models.py
msgid "" msgid ""
"Title specific for this run of a course. Leave this value blank to default " "Title specific for this run of a course. Leave this value blank to default "
"to the parent course's title." "to the parent course's title."
...@@ -317,7 +317,7 @@ msgid "" ...@@ -317,7 +317,7 @@ msgid ""
"to default to the parent course's short_description attribute." "to default to the parent course's short_description attribute."
msgstr "" msgstr ""
#: apps/course_metadata/models.py #: apps/course_metadata/models.py apps/publisher/models.py
msgid "" msgid ""
"Full description specific for this run of a course. Leave this value blank " "Full description specific for this run of a course. Leave this value blank "
"to default to the parent course's full_description attribute." "to default to the parent course's full_description attribute."
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-21 13:39+0500\n" "POT-Creation-Date: 2017-07-13 17:03-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: static/js/catalogs-change-form.js #: static/js/catalogs-change-form.js
msgid "Preview" msgid "Preview"
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-21 13:39+0500\n" "POT-Creation-Date: 2017-07-13 17:02-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps/api/filters.py #: apps/api/filters.py
...@@ -364,7 +364,7 @@ msgstr "" ...@@ -364,7 +364,7 @@ msgstr ""
"Çöürsé nümßér förmät é.g ÇS002x, BÌÖ1.1x, BÌÖ1.2x Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт " "Çöürsé nümßér förmät é.g ÇS002x, BÌÖ1.1x, BÌÖ1.2x Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#" "αмєт, ¢σηѕє¢тєтυя α#"
#: apps/course_metadata/models.py #: apps/course_metadata/models.py apps/publisher/models.py
msgid "" msgid ""
"Title specific for this run of a course. Leave this value blank to default " "Title specific for this run of a course. Leave this value blank to default "
"to the parent course's title." "to the parent course's title."
...@@ -386,7 +386,7 @@ msgstr "" ...@@ -386,7 +386,7 @@ msgstr ""
"¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт " "¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт "
"ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαв#" "ηση ρяσι∂єηт, ѕυηт ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαв#"
#: apps/course_metadata/models.py #: apps/course_metadata/models.py apps/publisher/models.py
msgid "" msgid ""
"Full description specific for this run of a course. Leave this value blank " "Full description specific for this run of a course. Leave this value blank "
"to default to the parent course's full_description attribute." "to default to the parent course's full_description attribute."
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-21 13:39+0500\n" "POT-Creation-Date: 2017-07-13 17:03-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: static/js/catalogs-change-form.js #: static/js/catalogs-change-form.js
......
...@@ -21,7 +21,7 @@ django-taggit==0.22.1 ...@@ -21,7 +21,7 @@ django-taggit==0.22.1
django-taggit-autosuggest==0.3.0 django-taggit-autosuggest==0.3.0
django-taggit-serializer==0.1.5 django-taggit-serializer==0.1.5
django-waffle==0.11.1 django-waffle==0.11.1
djangorestframework==3.5.4 djangorestframework==3.6.3
djangorestframework-csv==1.4.1 djangorestframework-csv==1.4.1
djangorestframework-jwt==1.8.0 djangorestframework-jwt==1.8.0
djangorestframework-xml==1.3.0 djangorestframework-xml==1.3.0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment