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
2293ee20
Commit
2293ee20
authored
Aug 03, 2016
by
Bill DeRusha
Committed by
GitHub
Aug 03, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #195 from edx/bderusha/course-list
Add course listing page
parents
0f66ff0d
543d8db4
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
164 additions
and
10 deletions
+164
-10
course_discovery/apps/publisher/migrations/0003_auto_20160801_1757.py
+30
-0
course_discovery/apps/publisher/models.py
+3
-3
course_discovery/apps/publisher/tests/test_wrapper.py
+51
-0
course_discovery/apps/publisher/urls.py
+1
-0
course_discovery/apps/publisher/views.py
+20
-7
course_discovery/apps/publisher/wrappers.py
+26
-0
course_discovery/templates/publisher/course_runs_list.html
+33
-0
No files found.
course_discovery/apps/publisher/migrations/0003_auto_20160801_1757.py
0 → 100644
View file @
2293ee20
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
sortedm2m.fields
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'publisher'
,
'0002_auto_20160729_1027'
),
]
operations
=
[
migrations
.
AlterField
(
model_name
=
'course'
,
name
=
'organizations'
,
field
=
models
.
ManyToManyField
(
blank
=
True
,
related_name
=
'publisher_courses'
,
to
=
'course_metadata.Organization'
,
verbose_name
=
'Partner Name'
),
),
migrations
.
AlterField
(
model_name
=
'courserun'
,
name
=
'course'
,
field
=
models
.
ForeignKey
(
related_name
=
'publisher_course_runs'
,
to
=
'publisher.Course'
),
),
migrations
.
AlterField
(
model_name
=
'courserun'
,
name
=
'staff'
,
field
=
sortedm2m
.
fields
.
SortedManyToManyField
(
blank
=
True
,
related_name
=
'publisher_course_runs_staffed'
,
help_text
=
None
,
to
=
'course_metadata.Person'
),
),
]
course_discovery/apps/publisher/models.py
View file @
2293ee20
...
@@ -28,7 +28,7 @@ class Course(TimeStampedModel, ChangedByMixin):
...
@@ -28,7 +28,7 @@ class Course(TimeStampedModel, ChangedByMixin):
)
)
full_description
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'About this course'
))
full_description
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'About this course'
))
organizations
=
models
.
ManyToManyField
(
organizations
=
models
.
ManyToManyField
(
Organization
,
null
=
True
,
blank
=
True
,
related_name
=
'publisher_courses'
,
verbose_name
=
_
(
'Partner Name'
)
Organization
,
blank
=
True
,
related_name
=
'publisher_courses'
,
verbose_name
=
_
(
'Partner Name'
)
)
)
level_type
=
models
.
ForeignKey
(
level_type
=
models
.
ForeignKey
(
LevelType
,
default
=
None
,
null
=
True
,
blank
=
True
,
related_name
=
'publisher_courses'
,
verbose_name
=
_
(
'Course level'
)
LevelType
,
default
=
None
,
null
=
True
,
blank
=
True
,
related_name
=
'publisher_courses'
,
verbose_name
=
_
(
'Course level'
)
...
@@ -70,7 +70,7 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
...
@@ -70,7 +70,7 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
(
PRIORITY_LEVEL_5
,
_
(
'Level 5'
)),
(
PRIORITY_LEVEL_5
,
_
(
'Level 5'
)),
)
)
course
=
models
.
ForeignKey
(
Course
)
course
=
models
.
ForeignKey
(
Course
,
related_name
=
'publisher_course_runs'
)
lms_course_id
=
models
.
CharField
(
max_length
=
255
,
unique
=
True
,
null
=
True
,
blank
=
True
)
lms_course_id
=
models
.
CharField
(
max_length
=
255
,
unique
=
True
,
null
=
True
,
blank
=
True
)
start
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
start
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
...
@@ -81,7 +81,7 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
...
@@ -81,7 +81,7 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
pacing_type
=
models
.
CharField
(
pacing_type
=
models
.
CharField
(
max_length
=
255
,
choices
=
CourseMetadataCourseRun
.
PACING_CHOICES
,
db_index
=
True
,
null
=
True
,
blank
=
True
max_length
=
255
,
choices
=
CourseMetadataCourseRun
.
PACING_CHOICES
,
db_index
=
True
,
null
=
True
,
blank
=
True
)
)
staff
=
SortedManyToManyField
(
Person
,
null
=
True
,
blank
=
True
,
related_name
=
'publisher_course_runs_staffed'
)
staff
=
SortedManyToManyField
(
Person
,
blank
=
True
,
related_name
=
'publisher_course_runs_staffed'
)
min_effort
=
models
.
PositiveSmallIntegerField
(
min_effort
=
models
.
PositiveSmallIntegerField
(
null
=
True
,
blank
=
True
,
null
=
True
,
blank
=
True
,
help_text
=
_
(
'Estimated minimum number of hours per week needed to complete a course run.'
))
help_text
=
_
(
'Estimated minimum number of hours per week needed to complete a course run.'
))
...
...
course_discovery/apps/publisher/tests/test_wrapper.py
0 → 100644
View file @
2293ee20
# pylint: disable=no-member
from
django.test
import
TestCase
from
unittest
import
mock
from
course_discovery.apps.course_metadata.tests.factories
import
CourseRunFactory
,
OrganizationFactory
from
course_discovery.apps.course_metadata.models
import
CourseOrganization
from
course_discovery.apps.publisher.wrappers
import
CourseRunWrapper
class
CourseRunWrapperTests
(
TestCase
):
""" Tests for the publisher `BaseWrapper` model. """
def
setUp
(
self
):
super
(
CourseRunWrapperTests
,
self
)
.
setUp
()
self
.
course_run
=
CourseRunFactory
()
course
=
self
.
course_run
.
course
organization_1
=
OrganizationFactory
()
organization_2
=
OrganizationFactory
()
CourseOrganization
.
objects
.
create
(
course
=
course
,
organization
=
organization_1
,
relation_type
=
CourseOrganization
.
OWNER
)
CourseOrganization
.
objects
.
create
(
course
=
course
,
organization
=
organization_2
,
relation_type
=
CourseOrganization
.
OWNER
)
course
.
save
()
self
.
wrapped_course_run
=
CourseRunWrapper
(
self
.
course_run
)
def
test_title
(
self
):
""" Verify that the wrapper can override course_run title. """
self
.
assertEqual
(
self
.
wrapped_course_run
.
title
,
self
.
course_run
.
course
.
title
)
def
test_partner
(
self
):
""" Verify that the wrapper can return partner values. """
partner
=
"/"
.
join
([
org
.
key
for
org
in
self
.
course_run
.
course
.
organizations
.
all
()])
self
.
assertEqual
(
self
.
wrapped_course_run
.
partner
,
partner
)
def
test_model_attr
(
self
):
""" Verify that the wrapper passes through object values not defined on wrapper. """
self
.
assertEqual
(
self
.
wrapped_course_run
.
key
,
self
.
course_run
.
key
)
def
test_callable
(
self
):
mock_callable
=
mock
.
Mock
(
return_value
=
'callable_value'
)
mock_obj
=
mock
.
MagicMock
(
callable_attr
=
mock_callable
)
wrapper
=
CourseRunWrapper
(
mock_obj
)
self
.
assertEqual
(
wrapper
.
callable_attr
(),
'callable_value'
)
course_discovery/apps/publisher/urls.py
View file @
2293ee20
...
@@ -8,6 +8,7 @@ from course_discovery.apps.publisher import views
...
@@ -8,6 +8,7 @@ from course_discovery.apps.publisher import views
urlpatterns
=
[
urlpatterns
=
[
url
(
r'^courses/new$'
,
views
.
CreateCourseView
.
as_view
(),
name
=
'publisher_courses_new'
),
url
(
r'^courses/new$'
,
views
.
CreateCourseView
.
as_view
(),
name
=
'publisher_courses_new'
),
url
(
r'^courses/(?P<pk>\d+)/edit/$'
,
views
.
UpdateCourseView
.
as_view
(),
name
=
'publisher_courses_edit'
),
url
(
r'^courses/(?P<pk>\d+)/edit/$'
,
views
.
UpdateCourseView
.
as_view
(),
name
=
'publisher_courses_edit'
),
url
(
r'^course_runs/$'
,
views
.
CourseRunListView
.
as_view
(),
name
=
'publisher_course_runs'
),
url
(
r'^course_runs/new$'
,
views
.
CreateCourseRunView
.
as_view
(),
name
=
'publisher_course_runs_new'
),
url
(
r'^course_runs/new$'
,
views
.
CreateCourseRunView
.
as_view
(),
name
=
'publisher_course_runs_new'
),
url
(
r'^course_runs/(?P<pk>\d+)/edit/$'
,
views
.
UpdateCourseRunView
.
as_view
(),
name
=
'publisher_course_runs_edit'
),
url
(
r'^course_runs/(?P<pk>\d+)/edit/$'
,
views
.
UpdateCourseRunView
.
as_view
(),
name
=
'publisher_course_runs_edit'
),
url
(
r'^seats/new$'
,
views
.
CreateSeatView
.
as_view
(),
name
=
'publisher_seats_new'
),
url
(
r'^seats/new$'
,
views
.
CreateSeatView
.
as_view
(),
name
=
'publisher_seats_new'
),
...
...
course_discovery/apps/publisher/views.py
View file @
2293ee20
...
@@ -3,15 +3,28 @@ Course publisher views.
...
@@ -3,15 +3,28 @@ Course publisher views.
"""
"""
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django.http
import
HttpResponseRedirect
from
django.http
import
HttpResponseRedirect
from
django.views.generic
import
edit
from
django.views.generic.edit
import
CreateView
,
UpdateView
from
django.views.generic.list
import
ListView
from
course_discovery.apps.publisher.forms
import
CourseForm
,
CourseRunForm
,
SeatForm
from
course_discovery.apps.publisher.forms
import
CourseForm
,
CourseRunForm
,
SeatForm
from
course_discovery.apps.publisher.models
import
Course
,
CourseRun
,
Seat
from
course_discovery.apps.publisher.models
import
Course
,
CourseRun
,
Seat
from
course_discovery.apps.publisher.wrappers
import
CourseRunWrapper
class
CourseRunListView
(
ListView
):
""" Create Course View."""
template_name
=
'publisher/course_runs_list.html'
def
get_queryset
(
self
):
return
[
CourseRunWrapper
(
course_run
)
for
course_run
in
CourseRun
.
objects
.
select_related
(
'course'
)
.
all
()
]
SEATS_HIDDEN_FIELDS
=
[
'price'
,
'currency'
,
'upgrade_deadline'
,
'credit_provider'
,
'credit_hours'
]
SEATS_HIDDEN_FIELDS
=
[
'price'
,
'currency'
,
'upgrade_deadline'
,
'credit_provider'
,
'credit_hours'
]
# pylint: disable=attribute-defined-outside-init
# pylint: disable=attribute-defined-outside-init
class
CreateCourseView
(
edit
.
CreateView
):
class
CreateCourseView
(
CreateView
):
""" Create Course View."""
""" Create Course View."""
model
=
Course
model
=
Course
form_class
=
CourseForm
form_class
=
CourseForm
...
@@ -26,7 +39,7 @@ class CreateCourseView(edit.CreateView):
...
@@ -26,7 +39,7 @@ class CreateCourseView(edit.CreateView):
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
class
UpdateCourseView
(
edit
.
UpdateView
):
class
UpdateCourseView
(
UpdateView
):
""" Update Course View."""
""" Update Course View."""
model
=
Course
model
=
Course
form_class
=
CourseForm
form_class
=
CourseForm
...
@@ -41,7 +54,7 @@ class UpdateCourseView(edit.UpdateView):
...
@@ -41,7 +54,7 @@ class UpdateCourseView(edit.UpdateView):
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
class
CreateCourseRunView
(
edit
.
CreateView
):
class
CreateCourseRunView
(
CreateView
):
""" Create Course Run View."""
""" Create Course Run View."""
model
=
CourseRun
model
=
CourseRun
form_class
=
CourseRunForm
form_class
=
CourseRunForm
...
@@ -56,7 +69,7 @@ class CreateCourseRunView(edit.CreateView):
...
@@ -56,7 +69,7 @@ class CreateCourseRunView(edit.CreateView):
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
class
UpdateCourseRunView
(
edit
.
UpdateView
):
class
UpdateCourseRunView
(
UpdateView
):
""" Update Course Run View."""
""" Update Course Run View."""
model
=
CourseRun
model
=
CourseRun
form_class
=
CourseRunForm
form_class
=
CourseRunForm
...
@@ -71,7 +84,7 @@ class UpdateCourseRunView(edit.UpdateView):
...
@@ -71,7 +84,7 @@ class UpdateCourseRunView(edit.UpdateView):
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
class
CreateSeatView
(
edit
.
CreateView
):
class
CreateSeatView
(
CreateView
):
""" Create Seat View."""
""" Create Seat View."""
model
=
Seat
model
=
Seat
form_class
=
SeatForm
form_class
=
SeatForm
...
@@ -91,7 +104,7 @@ class CreateSeatView(edit.CreateView):
...
@@ -91,7 +104,7 @@ class CreateSeatView(edit.CreateView):
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
class
UpdateSeatView
(
edit
.
UpdateView
):
class
UpdateSeatView
(
UpdateView
):
""" Update Seat View."""
""" Update Seat View."""
model
=
Seat
model
=
Seat
form_class
=
SeatForm
form_class
=
SeatForm
...
...
course_discovery/apps/publisher/wrappers.py
0 → 100644
View file @
2293ee20
"""Publisher Wrapper Classes"""
class
BaseWrapper
(
object
):
def
__init__
(
self
,
wrapped_obj
):
self
.
wrapped_obj
=
wrapped_obj
def
__getattr__
(
self
,
attr
):
orig_attr
=
self
.
wrapped_obj
.
__getattribute__
(
attr
)
if
callable
(
orig_attr
):
def
hooked
(
*
args
,
**
kwargs
):
return
orig_attr
(
*
args
,
**
kwargs
)
return
hooked
else
:
return
orig_attr
class
CourseRunWrapper
(
BaseWrapper
):
"""Decorator for the ``CourseRun`` model."""
@property
def
title
(
self
):
return
self
.
wrapped_obj
.
course
.
title
@property
def
partner
(
self
):
return
'/'
.
join
([
org
.
key
for
org
in
self
.
wrapped_obj
.
course
.
organizations
.
all
()])
course_discovery/templates/publisher/course_runs_list.html
0 → 100644
View file @
2293ee20
{% extends 'base.html' %}
{% load i18n %}
{% block title %}
{% trans "Course Run List" %}
{% endblock title %}
{% block content %}
<div
class=
"layout-full layout"
>
<div
class=
"card"
>
<h4
class=
"hd-4"
>
{% trans "Course Run List" %}
</h4>
<table
class=
"table"
>
<tr>
<th>
{% trans "Course Title" %}
</th>
<th>
{% trans "Partner" %}
</th>
<th>
{% trans "Target Content?" %}
</th>
<th>
{% trans "Priority" %}
</th>
<th>
{% trans "Last Updated" %}
</th>
</tr>
{% for course_run in object_list %}
<tr>
<td>
{{ course_run.title }}
</td>
<td>
{{ course_run.partner }}
</td>
<td>
{{ course_run.target_content }}
</td>
<td>
{{ course_run.priority }}
</td>
<td>
{{ course_run.modified }}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}
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