Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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
edx-platform
Commits
dffbc69a
Commit
dffbc69a
authored
Feb 02, 2016
by
Calen Pennington
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11329 from cpennington/fix-cert-type-names
Fix the help text for cert_name_short and cert_name_long
parents
97955251
4191ea00
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
211 additions
and
6 deletions
+211
-6
cms/djangoapps/contentstore/management/commands/clean_cert_name.py
+205
-0
common/lib/xmodule/xmodule/course_module.py
+6
-6
No files found.
cms/djangoapps/contentstore/management/commands/clean_cert_name.py
0 → 100644
View file @
dffbc69a
"""
A single-use management command that provides an interactive way to remove
erroneous certificate names.
"""
from
collections
import
namedtuple
from
django.core.management.base
import
BaseCommand
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore
import
ModuleStoreEnum
Result
=
namedtuple
(
"Result"
,
[
"course_key"
,
"cert_name_short"
,
"cert_name_long"
,
"should_clean"
])
class
Command
(
BaseCommand
):
"""
A management command that provides an interactive way to remove erroneous cert_name_long and
cert_name_short course attributes across both the Split and Mongo modulestores.
"""
help
=
'Allows manual clean-up of invalid cert_name_short and cert_name_long entries on CourseModules'
def
_mongo_results
(
self
):
"""
Return Result objects for any mongo-modulestore backend course that has
cert_name_short or cert_name_long set.
"""
# N.B. This code breaks many abstraction barriers. That's ok, because
# it's a one-time cleanup command.
# pylint: disable=protected-access
mongo_modulestore
=
modulestore
()
.
_get_modulestore_by_type
(
ModuleStoreEnum
.
Type
.
mongo
)
old_mongo_courses
=
mongo_modulestore
.
collection
.
find
({
"_id.category"
:
"course"
,
"$or"
:
[
{
"metadata.cert_name_short"
:
{
"$exists"
:
1
}},
{
"metadata.cert_name_long"
:
{
"$exists"
:
1
}},
]
},
{
"_id"
:
True
,
"metadata.cert_name_short"
:
True
,
"metadata.cert_name_long"
:
True
,
})
return
[
Result
(
mongo_modulestore
.
make_course_key
(
course
[
'_id'
][
'org'
],
course
[
'_id'
][
'course'
],
course
[
'_id'
][
'name'
],
),
course
[
'metadata'
]
.
get
(
'cert_name_short'
),
course
[
'metadata'
]
.
get
(
'cert_name_long'
),
True
)
for
course
in
old_mongo_courses
]
def
_split_results
(
self
):
"""
Return Result objects for any split-modulestore backend course that has
cert_name_short or cert_name_long set.
"""
# N.B. This code breaks many abstraction barriers. That's ok, because
# it's a one-time cleanup command.
# pylint: disable=protected-access
split_modulestore
=
modulestore
()
.
_get_modulestore_by_type
(
ModuleStoreEnum
.
Type
.
split
)
active_version_collection
=
split_modulestore
.
db_connection
.
course_index
structure_collection
=
split_modulestore
.
db_connection
.
structures
branches
=
active_version_collection
.
aggregate
([{
'$group'
:
{
'_id'
:
1
,
'draft'
:
{
'$push'
:
'$versions.draft-branch'
},
'published'
:
{
'$push'
:
'$versions.published-branch'
}
}
},
{
'$project'
:
{
'_id'
:
1
,
'branches'
:
{
'$setUnion'
:
[
'$draft'
,
'$published'
]}
}
}])[
'result'
][
0
][
'branches'
]
structures
=
list
(
structure_collection
.
find
({
'_id'
:
{
'$in'
:
branches
},
'blocks'
:
{
'$elemMatch'
:
{
'$and'
:
[
{
"block_type"
:
"course"
},
{
'$or'
:
[
{
'fields.cert_name_long'
:
{
'$exists'
:
True
}},
{
'fields.cert_name_short'
:
{
'$exists'
:
True
}}
]}
]
}}
},
{
'_id'
:
True
,
'blocks.fields.cert_name_long'
:
True
,
'blocks.fields.cert_name_short'
:
True
,
})
)
structure_map
=
{
struct
[
'_id'
]:
struct
for
struct
in
structures
}
structure_ids
=
[
struct
[
'_id'
]
for
struct
in
structures
]
split_mongo_courses
=
list
(
active_version_collection
.
find
({
'$or'
:
[
{
"versions.draft-branch"
:
{
'$in'
:
structure_ids
}},
{
"versions.published"
:
{
'$in'
:
structure_ids
}},
]
},
{
'org'
:
True
,
'course'
:
True
,
'run'
:
True
,
'versions'
:
True
,
}))
for
course
in
split_mongo_courses
:
draft
=
course
[
'versions'
]
.
get
(
'draft-branch'
)
if
draft
in
structure_map
:
draft_fields
=
structure_map
[
draft
][
'blocks'
][
0
]
.
get
(
'fields'
,
{})
else
:
draft_fields
=
{}
published
=
course
[
'versions'
]
.
get
(
'published'
)
if
published
in
structure_map
:
published_fields
=
structure_map
[
published
][
'blocks'
][
0
]
.
get
(
'fields'
,
{})
else
:
published_fields
=
{}
for
fields
in
(
draft_fields
,
published_fields
):
for
field
in
(
'cert_name_short'
,
'cert_name_long'
):
if
field
in
fields
:
course
[
field
]
=
fields
[
field
]
return
[
Result
(
split_modulestore
.
make_course_key
(
course
[
'org'
],
course
[
'course'
],
course
[
'run'
],
),
course
.
get
(
'cert_name_short'
),
course
.
get
(
'cert_name_long'
),
True
)
for
course
in
split_mongo_courses
]
def
_display
(
self
,
results
):
"""
Render a list of Result objects as a nicely formatted table.
"""
headers
=
[
"Course Key"
,
"cert_name_short"
,
"cert_name_short"
,
"Should clean?"
]
col_widths
=
[
max
(
len
(
unicode
(
result
[
col
]))
for
result
in
results
+
[
headers
])
for
col
in
range
(
len
(
results
[
0
]))
]
id_format
=
"{{:>{}}} |"
.
format
(
len
(
unicode
(
len
(
results
))))
col_format
=
"| {{:>{}}} |"
self
.
stdout
.
write
(
id_format
.
format
(
""
),
ending
=
''
)
for
header
,
width
in
zip
(
headers
,
col_widths
):
self
.
stdout
.
write
(
col_format
.
format
(
width
)
.
format
(
header
),
ending
=
''
)
self
.
stdout
.
write
(
''
)
for
idx
,
result
in
enumerate
(
results
):
self
.
stdout
.
write
(
id_format
.
format
(
idx
),
ending
=
''
)
for
col
,
width
in
zip
(
result
,
col_widths
):
self
.
stdout
.
write
(
col_format
.
format
(
width
)
.
format
(
unicode
(
col
)),
ending
=
''
)
self
.
stdout
.
write
(
""
)
def
_commit
(
self
,
results
):
"""
For each Result in ``results``, if ``should_clean`` is True, remove cert_name_long
and cert_name_short from the course and save in the backing modulestore.
"""
for
result
in
results
:
if
not
result
.
should_clean
:
continue
course
=
modulestore
()
.
get_course
(
result
.
course_key
)
del
course
.
cert_name_short
del
course
.
cert_name_long
modulestore
()
.
update_item
(
course
,
ModuleStoreEnum
.
UserID
.
mgmt_command
)
def
handle
(
self
,
*
args
,
**
options
):
results
=
self
.
_mongo_results
()
+
self
.
_split_results
()
self
.
stdout
.
write
(
"Type the index of a row to toggle whether it will be cleaned, "
"'commit' to remove all cert_name_short and cert_name_long values "
"from any rows marked for cleaning, or 'quit' to quit."
)
while
True
:
self
.
_display
(
results
)
command
=
raw_input
(
"<index>|commit|quit: "
)
.
strip
()
if
command
==
'quit'
:
return
elif
command
==
'commit'
:
self
.
_commit
(
results
)
return
elif
command
==
''
:
continue
else
:
index
=
int
(
command
)
results
[
index
]
=
results
[
index
]
.
_replace
(
should_clean
=
not
results
[
index
]
.
should_clean
)
common/lib/xmodule/xmodule/course_module.py
View file @
dffbc69a
...
...
@@ -495,9 +495,9 @@ class CourseFields(object):
## Course level Certificate Name overrides.
cert_name_short
=
String
(
help
=
_
(
"Use this setting only when generating PDF certificates. "
"Between quotation marks, enter the short name of the course to use on the certificate that "
"students receive when they complete the course."
'Use this setting only when generating PDF certificates. '
'Between quotation marks, enter the short name of the type of certificate that '
'students receive when they complete the course. For instance, "Certificate".'
),
display_name
=
_
(
"Certificate Name (Short)"
),
scope
=
Scope
.
settings
,
...
...
@@ -505,9 +505,9 @@ class CourseFields(object):
)
cert_name_long
=
String
(
help
=
_
(
"Use this setting only when generating PDF certificates. "
"Between quotation marks, enter the long name of the course to use on the certificate that students "
"receive when they complete the course."
'Use this setting only when generating PDF certificates. '
'Between quotation marks, enter the long name of the type of certificate that students '
'receive when they complete the course. For instance, "Certificate of Achievement".'
),
display_name
=
_
(
"Certificate Name (Long)"
),
scope
=
Scope
.
settings
,
...
...
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