From e4994b15cd40ec8b70f0dee0b8311cd238a18e66 Mon Sep 17 00:00:00 2001 From: Nate Hardison Date: Fri, 19 Jul 2013 10:28:43 -0700 Subject: [PATCH 1/2] Add mgmt cmd to generate anonymized ID mapping So that instructors have easy access to the mapping from anonymized IDs (a simple MD5 hash of the user ID that's used when integrating with third-party services like Qualtrics) to user IDs, we have a simple Django management command to generate a CSV mapping. To run, use the following: rake django-admin[anonymized_id_mapping,,,] And, of course, substitute the appropriate values for , , and . (E.g., lms, dev, and MITx/6.002x/Circuits) --- .../commands/anonymized_id_mapping.py | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 common/djangoapps/student/management/commands/anonymized_id_mapping.py diff --git a/common/djangoapps/student/management/commands/anonymized_id_mapping.py b/common/djangoapps/student/management/commands/anonymized_id_mapping.py new file mode 100644 index 000000000000..12153471e69b --- /dev/null +++ b/common/djangoapps/student/management/commands/anonymized_id_mapping.py @@ -0,0 +1,45 @@ +import csv +import sys + +from django.contrib.auth.models import User +from django.core.management.base import BaseCommand, CommandError + +from student.models import unique_id_for_user + +class Command(BaseCommand): + # It appears that with the way Rake invokes these commands, we can't + # have more than one arg passed through...annoying. + args = ("course_id", ) + + help = """ + Exports a CSV document mapping from a username to the anonymized, + unique user ID for every user in the specified course. + """ + + def handle(self, *args, **options): + if len(args) != 1: + raise CommandError("Usage: unique_id_mapping %s" % + " ".join(("<%s>" % arg for arg in Command.args))) + + course_id = args[0] + + # Generate the output filename from the course ID. + # Change slashes to dashes first, and then append .csv extension. + output_filename = course_id.replace('/', '-') + ".csv" + + # Figure out which students are enrolled in the course + students = User.objects.filter(courseenrollment__course_id=course_id) + if len(students) == 0: + self.stdout.write("No students enrolled in %s" % course_id) + return + + # Write mapping to output file in CSV format with a simple header + try: + with open(output_filename, 'wb') as output_file: + csv_writer = csv.writer(output_file) + csv_writer.writerow(("User ID", "Anonymized user ID")) + for student in students: + csv_writer.writerow((student.id, unique_id_for_user(student))) + except IOError: + raise CommandError("Error writing to file: %s" % output_filename) + From d6530fa633a6df96d7643b7b3c606ef115a408fd Mon Sep 17 00:00:00 2001 From: Joe Blaylock Date: Tue, 13 Aug 2013 11:35:23 -0700 Subject: [PATCH 2/2] Anonymized ID mapping fixups Fixups to Nate's anonymized id mapper, repairing pep8 and pylint errors, and rebasing on recent master. --- .../commands/anonymized_id_mapping.py | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/common/djangoapps/student/management/commands/anonymized_id_mapping.py b/common/djangoapps/student/management/commands/anonymized_id_mapping.py index 12153471e69b..6156d4bf1df6 100644 --- a/common/djangoapps/student/management/commands/anonymized_id_mapping.py +++ b/common/djangoapps/student/management/commands/anonymized_id_mapping.py @@ -1,19 +1,34 @@ +# -*- coding: utf8 -*- +"""Dump username,unique_id_for_user pairs as CSV. + +Give instructors easy access to the mapping from anonymized IDs to user IDs +with a simple Django management command to generate a CSV mapping. To run, use +the following: + +rake django-admin[anonymized_id_mapping,x,y,z] + +[Naturally, substitute the appropriate values for x, y, and z. (I.e., + lms, dev, and MITx/6.002x/Circuits)]""" + import csv -import sys from django.contrib.auth.models import User from django.core.management.base import BaseCommand, CommandError from student.models import unique_id_for_user + class Command(BaseCommand): + """Add our handler to the space where django-admin looks up commands.""" + # It appears that with the way Rake invokes these commands, we can't # have more than one arg passed through...annoying. args = ("course_id", ) - help = """ - Exports a CSV document mapping from a username to the anonymized, - unique user ID for every user in the specified course. + help = """Export a CSV mapping usernames to anonymized ids + + Exports a CSV document mapping each username in the specified course to + the anonymized, unique user ID. """ def handle(self, *args, **options):