Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
course-discovery
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
course-discovery
Commits
3a178f57
Commit
3a178f57
authored
Oct 23, 2017
by
Michael Frey
Committed by
Michael Frey
Oct 24, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the ability to access and filter courses by UUID and not just key.
LEARNER-2882
parent
70a95fcf
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
49 additions
and
3 deletions
+49
-3
course_discovery/apps/api/filters.py
+2
-1
course_discovery/apps/api/v1/tests/test_views/test_courses.py
+20
-0
course_discovery/apps/api/v1/views/courses.py
+26
-2
course_discovery/apps/course_metadata/constants.py
+1
-0
No files found.
course_discovery/apps/api/filters.py
View file @
3a178f57
...
...
@@ -128,10 +128,11 @@ class FilterSetMixin:
class
CourseFilter
(
filters
.
FilterSet
):
keys
=
CharListFilter
(
name
=
'key'
,
lookup_expr
=
'in'
)
uuids
=
UUIDListFilter
()
class
Meta
:
model
=
Course
fields
=
[
'keys'
]
fields
=
(
'keys'
,
'uuids'
,)
class
CourseRunFilter
(
FilterSetMixin
,
filters
.
FilterSet
):
...
...
course_discovery/apps/api/v1/tests/test_views/test_courses.py
View file @
3a178f57
...
...
@@ -37,6 +37,15 @@ class CourseViewSetTests(SerializationMixin, APITestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
data
,
self
.
serialize_course
(
self
.
course
))
def
test_get_uuid
(
self
):
""" Verify the endpoint returns the details for a single course with UUID. """
url
=
reverse
(
'api:v1:course-detail'
,
kwargs
=
{
'key'
:
self
.
course
.
uuid
})
with
self
.
assertNumQueries
(
21
):
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
data
,
self
.
serialize_course
(
self
.
course
))
def
test_get_exclude_deleted_programs
(
self
):
""" Verify the endpoint returns no deleted associated programs """
ProgramFactory
(
courses
=
[
self
.
course
],
status
=
ProgramStatus
.
Deleted
)
...
...
@@ -221,6 +230,17 @@ class CourseViewSetTests(SerializationMixin, APITestCase):
response
=
self
.
client
.
get
(
url
)
self
.
assertListEqual
(
response
.
data
[
'results'
],
self
.
serialize_course
(
courses
,
many
=
True
))
def
test_list_uuid_filter
(
self
):
""" Verify the endpoint returns a list of courses filtered by the specified uuid. """
courses
=
CourseFactory
.
create_batch
(
3
,
partner
=
self
.
partner
)
courses
=
sorted
(
courses
,
key
=
lambda
course
:
course
.
key
.
lower
())
uuids
=
','
.
join
([
str
(
course
.
uuid
)
for
course
in
courses
])
url
=
'{root}?uuids={uuids}'
.
format
(
root
=
reverse
(
'api:v1:course-list'
),
uuids
=
uuids
)
with
self
.
assertNumQueries
(
40
):
response
=
self
.
client
.
get
(
url
)
self
.
assertListEqual
(
response
.
data
[
'results'
],
self
.
serialize_course
(
courses
,
many
=
True
))
def
test_list_exclude_utm
(
self
):
""" Verify the endpoint returns marketing URLs without UTM parameters. """
url
=
reverse
(
'api:v1:course-list'
)
+
'?exclude_utm=1'
...
...
course_discovery/apps/api/v1/views/courses.py
View file @
3a178f57
import
re
from
django.db.models.functions
import
Lower
from
django.shortcuts
import
get_object_or_404
from
django_filters.rest_framework
import
DjangoFilterBackend
from
rest_framework
import
viewsets
from
rest_framework.permissions
import
IsAuthenticated
...
...
@@ -7,7 +10,7 @@ from course_discovery.apps.api import filters, serializers
from
course_discovery.apps.api.pagination
import
ProxiedPagination
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.constants
import
COURSE_ID_REGEX
from
course_discovery.apps.course_metadata.constants
import
COURSE_ID_REGEX
,
COURSE_UUID_REGEX
from
course_discovery.apps.course_metadata.models
import
Course
,
CourseRun
...
...
@@ -17,14 +20,35 @@ class CourseViewSet(viewsets.ReadOnlyModelViewSet):
filter_backends
=
(
DjangoFilterBackend
,)
filter_class
=
filters
.
CourseFilter
lookup_field
=
'key'
lookup_value_regex
=
COURSE_ID_REGEX
lookup_value_regex
=
COURSE_ID_REGEX
+
'|'
+
COURSE_UUID_REGEX
permission_classes
=
(
IsAuthenticated
,)
serializer_class
=
serializers
.
CourseWithProgramsSerializer
course_key_regex
=
re
.
compile
(
COURSE_ID_REGEX
)
course_uuid_regex
=
re
.
compile
(
COURSE_UUID_REGEX
)
# Explicitly support PageNumberPagination and LimitOffsetPagination. Future
# versions of this API should only support the system default, PageNumberPagination.
pagination_class
=
ProxiedPagination
def
get_object
(
self
):
queryset
=
self
.
filter_queryset
(
self
.
get_queryset
())
key
=
self
.
kwargs
[
'key'
]
if
self
.
course_key_regex
.
match
(
key
):
filter_key
=
'key'
elif
self
.
course_uuid_regex
.
match
(
key
):
filter_key
=
'uuid'
filter_kwargs
=
{
filter_key
:
key
}
obj
=
get_object_or_404
(
queryset
,
**
filter_kwargs
)
# May raise a permission denied
self
.
check_object_permissions
(
self
.
request
,
obj
)
return
obj
def
get_queryset
(
self
):
partner
=
self
.
request
.
site
.
partner
q
=
self
.
request
.
query_params
.
get
(
'q'
)
...
...
course_discovery/apps/course_metadata/constants.py
View file @
3a178f57
COURSE_ID_REGEX
=
r'[^/+]+(/|\+)[^/+]+'
COURSE_RUN_ID_REGEX
=
r'[^/+]+(/|\+)[^/+]+(/|\+)[^/]+'
COURSE_UUID_REGEX
=
r'[0-9a-f-]+'
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment