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
caf729cc
Commit
caf729cc
authored
Sep 02, 2016
by
Matthew Piatetsky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add program types to search endpoint
parent
17013506
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
56 additions
and
3 deletions
+56
-3
course_discovery/apps/api/serializers.py
+1
-1
course_discovery/apps/api/tests/test_serializers.py
+2
-0
course_discovery/apps/course_metadata/models.py
+29
-0
course_discovery/apps/course_metadata/search_indexes.py
+4
-0
course_discovery/apps/course_metadata/tests/test_models.py
+20
-2
No files found.
course_discovery/apps/api/serializers.py
View file @
caf729cc
...
@@ -45,7 +45,7 @@ COURSE_RUN_FACET_FIELD_QUERIES = {
...
@@ -45,7 +45,7 @@ COURSE_RUN_FACET_FIELD_QUERIES = {
COURSE_RUN_SEARCH_FIELDS
=
(
COURSE_RUN_SEARCH_FIELDS
=
(
'text'
,
'key'
,
'title'
,
'short_description'
,
'full_description'
,
'start'
,
'end'
,
'enrollment_start'
,
'text'
,
'key'
,
'title'
,
'short_description'
,
'full_description'
,
'start'
,
'end'
,
'enrollment_start'
,
'enrollment_end'
,
'pacing_type'
,
'language'
,
'transcript_languages'
,
'marketing_url'
,
'content_type'
,
'org'
,
'enrollment_end'
,
'pacing_type'
,
'language'
,
'transcript_languages'
,
'marketing_url'
,
'content_type'
,
'org'
,
'number'
,
'seat_types'
,
'image_url'
,
'type'
,
'level_type'
,
'availability'
,
'published'
,
'partner'
,
'number'
,
'seat_types'
,
'image_url'
,
'type'
,
'level_type'
,
'availability'
,
'published'
,
'partner'
,
'program_types'
,
)
)
PROGRAM_FACET_FIELD_OPTIONS
=
{
PROGRAM_FACET_FIELD_OPTIONS
=
{
...
...
course_discovery/apps/api/tests/test_serializers.py
View file @
caf729cc
...
@@ -584,6 +584,7 @@ class AffiliateWindowSerializerTests(TestCase):
...
@@ -584,6 +584,7 @@ class AffiliateWindowSerializerTests(TestCase):
class
CourseRunSearchSerializerTests
(
TestCase
):
class
CourseRunSearchSerializerTests
(
TestCase
):
def
test_data
(
self
):
def
test_data
(
self
):
course_run
=
CourseRunFactory
(
transcript_languages
=
LanguageTag
.
objects
.
filter
(
code__in
=
[
'en-us'
,
'zh-cn'
]))
course_run
=
CourseRunFactory
(
transcript_languages
=
LanguageTag
.
objects
.
filter
(
code__in
=
[
'en-us'
,
'zh-cn'
]))
ProgramFactory
(
courses
=
[
course_run
.
course
])
serializer
=
self
.
serialize_course_run
(
course_run
)
serializer
=
self
.
serialize_course_run
(
course_run
)
course_run_key
=
CourseKey
.
from_string
(
course_run
.
key
)
course_run_key
=
CourseKey
.
from_string
(
course_run
.
key
)
...
@@ -610,6 +611,7 @@ class CourseRunSearchSerializerTests(TestCase):
...
@@ -610,6 +611,7 @@ class CourseRunSearchSerializerTests(TestCase):
'availability'
:
course_run
.
availability
,
'availability'
:
course_run
.
availability
,
'published'
:
course_run
.
status
==
CourseRun
.
Status
.
Published
,
'published'
:
course_run
.
status
==
CourseRun
.
Status
.
Published
,
'partner'
:
course_run
.
course
.
partner
.
short_code
,
'partner'
:
course_run
.
course
.
partner
.
short_code
,
'program_types'
:
course_run
.
program_types
,
}
}
self
.
assertDictEqual
(
serializer
.
data
,
expected
)
self
.
assertDictEqual
(
serializer
.
data
,
expected
)
...
...
course_discovery/apps/course_metadata/models.py
View file @
caf729cc
...
@@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _
...
@@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _
from
django_extensions.db.fields
import
AutoSlugField
from
django_extensions.db.fields
import
AutoSlugField
from
django_extensions.db.models
import
TimeStampedModel
from
django_extensions.db.models
import
TimeStampedModel
from
djchoices
import
DjangoChoices
,
ChoiceItem
from
djchoices
import
DjangoChoices
,
ChoiceItem
from
haystack
import
connections
from
haystack.query
import
SearchQuerySet
from
haystack.query
import
SearchQuerySet
from
simple_history.models
import
HistoricalRecords
from
simple_history.models
import
HistoricalRecords
from
sortedm2m.fields
import
SortedManyToManyField
from
sortedm2m.fields
import
SortedManyToManyField
...
@@ -307,6 +308,19 @@ class Course(TimeStampedModel):
...
@@ -307,6 +308,19 @@ class Course(TimeStampedModel):
ids
=
[
result
.
pk
for
result
in
results
]
ids
=
[
result
.
pk
for
result
in
results
]
return
cls
.
objects
.
filter
(
pk__in
=
ids
)
return
cls
.
objects
.
filter
(
pk__in
=
ids
)
def
save
(
self
,
*
args
,
**
kwargs
):
super
(
Course
,
self
)
.
save
(
*
args
,
**
kwargs
)
try
:
self
.
reindex_course_runs
()
except
Exception
:
# pylint: disable=broad-except
logger
.
exception
(
"An error occurred while attempting to reindex the course runs"
"of Course with key: [{key}]."
.
format
(
key
=
self
.
key
))
def
reindex_course_runs
(
self
):
index
=
connections
[
'default'
]
.
get_unified_index
()
.
get_index
(
CourseRun
)
for
course_run
in
self
.
course_runs
.
all
():
index
.
update_object
(
course_run
)
class
CourseRun
(
TimeStampedModel
):
class
CourseRun
(
TimeStampedModel
):
""" CourseRun model. """
""" CourseRun model. """
...
@@ -366,6 +380,10 @@ class CourseRun(TimeStampedModel):
...
@@ -366,6 +380,10 @@ class CourseRun(TimeStampedModel):
objects
=
CourseRunQuerySet
.
as_manager
()
objects
=
CourseRunQuerySet
.
as_manager
()
@property
@property
def
program_types
(
self
):
return
[
program
.
type
.
name
for
program
in
self
.
programs
.
all
()]
@property
def
marketing_url
(
self
):
def
marketing_url
(
self
):
if
self
.
slug
:
if
self
.
slug
:
path
=
'course/{slug}'
.
format
(
slug
=
self
.
slug
)
path
=
'course/{slug}'
.
format
(
slug
=
self
.
slug
)
...
@@ -724,6 +742,17 @@ class Program(TimeStampedModel):
...
@@ -724,6 +742,17 @@ class Program(TimeStampedModel):
publisher
.
publish_program
(
self
)
publisher
.
publish_program
(
self
)
else
:
else
:
super
(
Program
,
self
)
.
save
(
*
args
,
**
kwargs
)
super
(
Program
,
self
)
.
save
(
*
args
,
**
kwargs
)
self
.
reindex_courses
()
def
reindex_courses
(
self
):
try
:
index
=
connections
[
'default'
]
.
get_unified_index
()
.
get_index
(
Course
)
for
course
in
self
.
courses
.
all
():
index
.
update_object
(
course
)
course
.
reindex_course_runs
()
except
Exception
:
# pylint: disable=broad-except
logger
.
exception
(
"An error occurred while attempting to reindex the courses"
"of Program with uuid: [{uuid}]."
.
format
(
uuid
=
self
.
uuid
))
class
PersonSocialNetwork
(
AbstractSocialNetworkModel
):
class
PersonSocialNetwork
(
AbstractSocialNetworkModel
):
...
...
course_discovery/apps/course_metadata/search_indexes.py
View file @
caf729cc
...
@@ -112,6 +112,7 @@ class CourseRunIndex(BaseCourseIndex, indexes.Indexable):
...
@@ -112,6 +112,7 @@ class CourseRunIndex(BaseCourseIndex, indexes.Indexable):
type
=
indexes
.
CharField
(
model_attr
=
'type'
,
null
=
True
,
faceted
=
True
)
type
=
indexes
.
CharField
(
model_attr
=
'type'
,
null
=
True
,
faceted
=
True
)
image_url
=
indexes
.
CharField
(
model_attr
=
'card_image_url'
,
null
=
True
)
image_url
=
indexes
.
CharField
(
model_attr
=
'card_image_url'
,
null
=
True
)
partner
=
indexes
.
CharField
(
null
=
True
,
faceted
=
True
)
partner
=
indexes
.
CharField
(
null
=
True
,
faceted
=
True
)
program_types
=
indexes
.
MultiValueField
()
published
=
indexes
.
BooleanField
(
null
=
False
,
faceted
=
True
)
published
=
indexes
.
BooleanField
(
null
=
False
,
faceted
=
True
)
def
prepare_partner
(
self
,
obj
):
def
prepare_partner
(
self
,
obj
):
...
@@ -147,6 +148,9 @@ class CourseRunIndex(BaseCourseIndex, indexes.Indexable):
...
@@ -147,6 +148,9 @@ class CourseRunIndex(BaseCourseIndex, indexes.Indexable):
def
prepare_marketing_url
(
self
,
obj
):
def
prepare_marketing_url
(
self
,
obj
):
return
obj
.
marketing_url
return
obj
.
marketing_url
def
prepare_program_types
(
self
,
obj
):
return
obj
.
program_types
class
ProgramIndex
(
BaseIndex
,
indexes
.
Indexable
,
OrganizationsMixin
):
class
ProgramIndex
(
BaseIndex
,
indexes
.
Indexable
,
OrganizationsMixin
):
model
=
Program
model
=
Program
...
...
course_discovery/apps/course_metadata/tests/test_models.py
View file @
caf729cc
...
@@ -2,6 +2,7 @@ import itertools
...
@@ -2,6 +2,7 @@ import itertools
from
decimal
import
Decimal
from
decimal
import
Decimal
import
ddt
import
ddt
import
mock
from
dateutil.parser
import
parse
from
dateutil.parser
import
parse
from
django.conf
import
settings
from
django.conf
import
settings
from
django.db
import
IntegrityError
from
django.db
import
IntegrityError
...
@@ -15,8 +16,8 @@ from course_discovery.apps.core.tests.helpers import make_image_file
...
@@ -15,8 +16,8 @@ from course_discovery.apps.core.tests.helpers import make_image_file
from
course_discovery.apps.core.utils
import
SearchQuerySetWrapper
from
course_discovery.apps.core.utils
import
SearchQuerySetWrapper
from
course_discovery.apps.course_metadata.models
import
(
from
course_discovery.apps.course_metadata.models
import
(
AbstractMediaModel
,
AbstractNamedModel
,
AbstractValueModel
,
AbstractMediaModel
,
AbstractNamedModel
,
AbstractValueModel
,
CorporateEndorsement
,
Course
,
CourseRun
,
Endorsement
,
CorporateEndorsement
,
Program
,
Course
,
CourseRun
,
Endorsement
,
FAQ
,
SeatType
,
Program
FAQ
,
SeatType
)
)
from
course_discovery.apps.course_metadata.tests
import
factories
,
toggle_switch
from
course_discovery.apps.course_metadata.tests
import
factories
,
toggle_switch
from
course_discovery.apps.course_metadata.tests.factories
import
CourseRunFactory
,
ImageFactory
from
course_discovery.apps.course_metadata.tests.factories
import
CourseRunFactory
,
ImageFactory
...
@@ -47,6 +48,11 @@ class CourseTests(TestCase):
...
@@ -47,6 +48,11 @@ class CourseTests(TestCase):
actual
=
list
(
Course
.
search
(
query
)
.
order_by
(
'key'
))
actual
=
list
(
Course
.
search
(
query
)
.
order_by
(
'key'
))
self
.
assertEqual
(
actual
,
courses
)
self
.
assertEqual
(
actual
,
courses
)
def
test_course_run_update_caught_exception
(
self
):
""" Test that the index update process failing will not cause the course save to error """
with
mock
.
patch
.
object
(
Course
,
'reindex_course_runs'
,
side_effect
=
Exception
):
self
.
course
.
save
()
@ddt.ddt
@ddt.ddt
class
CourseRunTests
(
TestCase
):
class
CourseRunTests
(
TestCase
):
...
@@ -150,6 +156,13 @@ class CourseRunTests(TestCase):
...
@@ -150,6 +156,13 @@ class CourseRunTests(TestCase):
course_run
=
CourseRunFactory
(
slug
=
slug
)
course_run
=
CourseRunFactory
(
slug
=
slug
)
self
.
assertIsNone
(
course_run
.
marketing_url
)
self
.
assertIsNone
(
course_run
.
marketing_url
)
def
test_program_types
(
self
):
""" Verify the property retrieves program types correctly based on programs. """
courses
=
[
self
.
course_run
.
course
]
program
=
factories
.
ProgramFactory
(
courses
=
courses
)
other_program
=
factories
.
ProgramFactory
(
courses
=
courses
)
self
.
assertCountEqual
(
self
.
course_run
.
program_types
,
[
program
.
type
.
name
,
other_program
.
type
.
name
])
class
OrganizationTests
(
TestCase
):
class
OrganizationTests
(
TestCase
):
""" Tests for the `Organization` model. """
""" Tests for the `Organization` model. """
...
@@ -409,6 +422,11 @@ class ProgramTests(MarketingSitePublisherTestMixin, TestCase):
...
@@ -409,6 +422,11 @@ class ProgramTests(MarketingSitePublisherTestMixin, TestCase):
self
.
assertEqual
(
len
(
responses
.
calls
),
0
)
self
.
assertEqual
(
len
(
responses
.
calls
),
0
)
toggle_switch
(
'publish_program_to_marketing_site'
,
False
)
toggle_switch
(
'publish_program_to_marketing_site'
,
False
)
def
test_course_update_caught_exception
(
self
):
""" Test that the index update process failing will not cause the program save to error """
with
mock
.
patch
.
object
(
Course
,
'reindex_course_runs'
,
side_effect
=
Exception
):
self
.
program
.
save
()
class
PersonSocialNetworkTests
(
TestCase
):
class
PersonSocialNetworkTests
(
TestCase
):
"""Tests of the PersonSocialNetwork model."""
"""Tests of the PersonSocialNetwork model."""
...
...
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