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
870f2625
Commit
870f2625
authored
Mar 05, 2015
by
E. Kolpakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added management command to export all users' discussion participation into csv file
parent
f5351318
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
156 additions
and
0 deletions
+156
-0
lms/djangoapps/django_comment_client/management/commands/export_discussion_participation.py
+114
-0
lms/djangoapps/django_comment_client/tests/test_utils.py
+17
-0
lms/djangoapps/django_comment_client/utils.py
+21
-0
lms/lib/comment_client/user.py
+4
-0
No files found.
lms/djangoapps/django_comment_client/management/commands/export_discussion_participation.py
0 → 100644
View file @
870f2625
import
csv
from
datetime
import
datetime
from
django.core.management.base
import
BaseCommand
,
CommandError
from
opaque_keys
import
InvalidKeyError
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
courseware.courses
import
get_course
from
student.models
import
CourseEnrollment
from
lms.lib.comment_client.user
import
User
import
django_comment_client.utils
as
utils
class
_Fields
:
USERNAME
=
u"username"
EMAIL
=
u"email"
FIRST_NAME
=
u"first_name"
LAST_NAME
=
u"last_name"
THREADS
=
u"num_threads"
COMMENTS
=
u"num_comments"
REPLIES
=
u"num_replies"
UPVOTES
=
u"num_upvotes"
FOLOWERS
=
u"num_thread_followers"
COMMENTS_GENERATED
=
u"num_comments_generated"
def
_make_social_stats
(
threads
=
0
,
comments
=
0
,
replies
=
0
,
upvotes
=
0
,
followers
=
0
,
comments_generated
=
0
):
return
{
_Fields
.
THREADS
:
threads
,
_Fields
.
COMMENTS
:
comments
,
_Fields
.
REPLIES
:
replies
,
_Fields
.
UPVOTES
:
upvotes
,
_Fields
.
FOLOWERS
:
followers
,
_Fields
.
COMMENTS_GENERATED
:
comments_generated
,
}
class
Command
(
BaseCommand
):
args
=
"<course_id> <output_file_location>"
row_order
=
[
_Fields
.
USERNAME
,
_Fields
.
EMAIL
,
_Fields
.
FIRST_NAME
,
_Fields
.
LAST_NAME
,
_Fields
.
THREADS
,
_Fields
.
COMMENTS
,
_Fields
.
REPLIES
,
_Fields
.
UPVOTES
,
_Fields
.
FOLOWERS
,
_Fields
.
COMMENTS_GENERATED
]
def
_get_users
(
self
,
course_key
):
users
=
CourseEnrollment
.
users_enrolled_in
(
course_key
)
return
{
user
.
id
:
user
for
user
in
users
}
def
_get_social_stats
(
self
,
course_key
):
return
{
int
(
user_id
):
data
for
user_id
,
data
in
User
.
all_social_stats
(
str
(
course_key
))
.
iteritems
()
}
def
_merge_user_data_and_social_stats
(
self
,
userdata
,
social_stats
):
result
=
[]
for
user_id
,
user
in
userdata
.
iteritems
():
user_record
=
{
_Fields
.
USERNAME
:
user
.
username
,
_Fields
.
EMAIL
:
user
.
email
,
_Fields
.
FIRST_NAME
:
user
.
first_name
,
_Fields
.
LAST_NAME
:
user
.
last_name
,
}
stats
=
social_stats
.
get
(
user_id
,
_make_social_stats
())
result
.
append
(
utils
.
merge_dict
(
user_record
,
stats
))
return
result
def
_output
(
self
,
data
,
output_stream
):
csv_writer
=
csv
.
DictWriter
(
output_stream
,
self
.
row_order
)
csv_writer
.
writeheader
()
for
row
in
sorted
(
data
,
key
=
lambda
item
:
item
[
'username'
]):
to_write
=
{
key
:
value
for
key
,
value
in
row
.
items
()
if
key
in
self
.
row_order
}
csv_writer
.
writerow
(
to_write
)
def
get_default_file_location
(
self
,
course_key
):
return
utils
.
format_filename
(
"social_stats_{course}_{date:
%
Y_
%
m_
%
d_
%
H_
%
M_
%
S}.csv"
.
format
(
course
=
course_key
,
date
=
datetime
.
utcnow
())
)
def
handle
(
self
,
*
args
,
**
options
):
if
not
args
:
raise
CommandError
(
"Course id not specified"
)
if
len
(
args
)
>
2
:
raise
CommandError
(
"Only one course id may be specifiied"
)
raw_course_key
=
args
[
0
]
if
len
(
args
)
==
1
:
output_file_location
=
self
.
get_default_file_location
(
raw_course_key
)
else
:
output_file_location
=
args
[
1
]
try
:
course_key
=
CourseKey
.
from_string
(
raw_course_key
)
except
InvalidKeyError
:
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
raw_course_key
)
course
=
get_course
(
course_key
)
if
not
course
:
raise
CommandError
(
"Invalid course id: {}"
.
format
(
course_key
))
users
=
self
.
_get_users
(
course_key
)
social_stats
=
self
.
_get_social_stats
(
course_key
)
merged_data
=
self
.
_merge_user_data_and_social_stats
(
users
,
social_stats
)
self
.
stdout
.
write
(
"Writing social stats to {}
\n
"
.
format
(
output_file_location
))
with
open
(
output_file_location
,
'wb'
)
as
output_stream
:
self
.
_output
(
merged_data
,
output_stream
)
self
.
stdout
.
write
(
"Success!
\n
"
)
\ No newline at end of file
lms/djangoapps/django_comment_client/tests/test_utils.py
View file @
870f2625
...
...
@@ -2,6 +2,7 @@
import
json
import
mock
import
ddt
from
datetime
import
datetime
from
pytz
import
UTC
from
django.core.urlresolvers
import
reverse
...
...
@@ -644,3 +645,18 @@ class RenderMustacheTests(TestCase):
"""
add_lookup
(
'main'
,
''
,
package
=
__name__
)
self
.
assertEqual
(
utils
.
render_mustache
(
'test.mustache'
,
{}),
'Testing 1 2 3.
\n
'
)
@ddt.ddt
class
FormatFilenameTests
(
TestCase
):
@ddt.unpack
@ddt.data
(
(
"normal.txt"
,
"normal.txt"
),
(
"normal_with_alnum.csv"
,
"normal_with_alnum.csv"
),
(
"normal_with_multiple_extensions.dot.csv"
,
"normal_with_multiple_extensions.dot.csv"
),
(
"contains/slashes.html"
,
"containsslashes.html"
),
(
"contains_symbols!@#$
%
^&*+=
\
|,.html"
,
"contains_symbols.html"
),
(
"contains spaces.org"
,
"contains_spaces.org"
),
)
def
test_format_filename
(
self
,
raw_filename
,
expected_output
):
self
.
assertEqual
(
utils
.
format_filename
(
raw_filename
),
expected_output
)
\ No newline at end of file
lms/djangoapps/django_comment_client/utils.py
View file @
870f2625
import
string
import
pytz
from
collections
import
defaultdict
import
logging
...
...
@@ -436,3 +438,21 @@ def safe_content(content, course_id, is_staff=False):
content
[
child_content_key
]
=
safe_children
return
content
def
format_filename
(
s
):
"""Take a string and return a valid filename constructed from the string.
Uses a whitelist approach: any characters not present in valid_chars are
removed. Also spaces are replaced with underscores.
Note: this method may produce invalid filenames such as ``, `.` or `..`
When I use this method I prepend a date string like '2009_01_15_19_46_32_'
and append a file extension like '.txt', so I avoid the potential of using
an invalid filename.
https://gist.github.com/seanh/93666
"""
valid_chars
=
"-_.()
%
s
%
s"
%
(
string
.
ascii_letters
,
string
.
digits
)
filename
=
''
.
join
(
c
for
c
in
s
if
c
in
valid_chars
)
filename
=
filename
.
replace
(
' '
,
'_'
)
return
filename
\ No newline at end of file
lms/lib/comment_client/user.py
View file @
870f2625
...
...
@@ -117,6 +117,10 @@ class User(models.Model):
def
social_stats
(
self
,
end_date
=
None
):
return
get_user_social_stats
(
self
.
id
,
self
.
course_id
,
end_date
=
end_date
)
@classmethod
def
all_social_stats
(
cls
,
course_id
,
end_date
=
None
):
return
get_user_social_stats
(
'*'
,
course_id
,
end_date
=
end_date
)
def
_retrieve
(
self
,
*
args
,
**
kwargs
):
url
=
self
.
url
(
action
=
'get'
,
params
=
self
.
attributes
)
retrieve_params
=
self
.
default_retrieve_params
.
copy
()
...
...
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