diff options
-rw-r--r-- | yaksh/file_utils.py | 5 | ||||
-rw-r--r-- | yaksh/test_views.py | 35 | ||||
-rw-r--r-- | yaksh/views.py | 53 |
3 files changed, 47 insertions, 46 deletions
diff --git a/yaksh/file_utils.py b/yaksh/file_utils.py index 0d80b8f..7aef249 100644 --- a/yaksh/file_utils.py +++ b/yaksh/file_utils.py @@ -52,6 +52,7 @@ def extract_files(zip_file, path=None): def is_csv(document): + ''' Check if document is csv with ',' as the delimiter''' try: try: content = document.read(1024).decode('utf-8') @@ -62,8 +63,8 @@ def is_csv(document): dialect = sniffer.sniff(content) document.seek(0) except (csv.Error, UnicodeDecodeError): - return False - return True + return False, None + return True, dialect def headers_present(dict_reader, headers): diff --git a/yaksh/test_views.py b/yaksh/test_views.py index 465fb30..9f46ba9 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -1792,21 +1792,20 @@ class TestCourseDetail(TestCase): self.student.delete() self.user1_course.delete() - def test_upload_users_with_correct_csv(self): # Given self.client.login( username=self.user1.username, password=self.user1_plaintext_pass ) - csv_file_path = os.path.join(settings.FIXTURE_DIRS, "users_correct.csv") + csv_file_path = os.path.join(FIXTURES_DIR_PATH, "users_correct.csv") csv_file = open(csv_file_path, 'rb') upload_file = SimpleUploadedFile(csv_file_path, csv_file.read()) # When response = self.client.post(reverse('yaksh:upload_users', - kwargs={'course_id': self.user1_course.id}), - data={'csv_file': upload_file}) + kwargs={'course_id': self.user1_course.id}), + data={'csv_file': upload_file}) csv_file.close() # Then @@ -1816,22 +1815,21 @@ class TestCourseDetail(TestCase): self.assertIn('upload_details', response.context) self.assertTemplateUsed(response, 'yaksh/course_detail.html') - def test_upload_users_with_wrong_csv(self): # Given self.client.login( username=self.user1.username, password=self.user1_plaintext_pass ) - csv_file_path = os.path.join(settings.FIXTURE_DIRS, "demo_questions.zip") + csv_file_path = os.path.join(FIXTURES_DIR_PATH, "demo_questions.zip") csv_file = open(csv_file_path, 'rb') upload_file = SimpleUploadedFile(csv_file_path, csv_file.read()) message = "The file uploaded is not a CSV file." # When response = self.client.post(reverse('yaksh:upload_users', - kwargs={'course_id': self.user1_course.id}), - data={'csv_file': upload_file}) + kwargs={'course_id': self.user1_course.id}), + data={'csv_file': upload_file}) csv_file.close() # Then @@ -1841,22 +1839,21 @@ class TestCourseDetail(TestCase): self.assertEqual(response.context['message'], message) self.assertTemplateUsed(response, 'yaksh/course_detail.html') - def test_upload_users_csv_with_missing_headers(self): # Given self.client.login( username=self.user1.username, password=self.user1_plaintext_pass ) - csv_file_path = os.path.join(settings.FIXTURE_DIRS, "users_some_headers_missing.csv") + csv_file_path = os.path.join(FIXTURES_DIR_PATH, "users_some_headers_missing.csv") csv_file = open(csv_file_path, 'rb') upload_file = SimpleUploadedFile(csv_file_path, csv_file.read()) message = "The CSV file does not contain the required headers" # When response = self.client.post(reverse('yaksh:upload_users', - kwargs={'course_id': self.user1_course.id}), - data={'csv_file': upload_file}) + kwargs={'course_id': self.user1_course.id}), + data={'csv_file': upload_file}) csv_file.close() # Then @@ -1872,14 +1869,14 @@ class TestCourseDetail(TestCase): username=self.user1.username, password=self.user1_plaintext_pass ) - csv_file_path = os.path.join(settings.FIXTURE_DIRS, "users_with_no_values.csv") + csv_file_path = os.path.join(FIXTURES_DIR_PATH, "users_with_no_values.csv") csv_file = open(csv_file_path, 'rb') upload_file = SimpleUploadedFile(csv_file_path, csv_file.read()) # When response = self.client.post(reverse('yaksh:upload_users', - kwargs={'course_id': self.user1_course.id}), - data={'csv_file': upload_file}) + kwargs={'course_id': self.user1_course.id}), + data={'csv_file': upload_file}) csv_file.close() # Then @@ -1889,7 +1886,6 @@ class TestCourseDetail(TestCase): self.assertIn("No rows in the CSV file", response.context['upload_details']) self.assertTemplateUsed(response, 'yaksh/course_detail.html') - def test_upload_users_csv_with_missing_values(self): ''' This test takes csv with 3 row values. @@ -1908,14 +1904,14 @@ class TestCourseDetail(TestCase): username=self.user1.username, password=self.user1_plaintext_pass ) - csv_file_path = os.path.join(settings.FIXTURE_DIRS, "users_some_values_missing.csv") + csv_file_path = os.path.join(FIXTURES_DIR_PATH, "users_some_values_missing.csv") csv_file = open(csv_file_path, 'rb') upload_file = SimpleUploadedFile(csv_file_path, csv_file.read()) # When response = self.client.post(reverse('yaksh:upload_users', - kwargs={'course_id': self.user1_course.id}), - data={'csv_file': upload_file}) + kwargs={'course_id': self.user1_course.id}), + data={'csv_file': upload_file}) csv_file.close() # Then @@ -1926,7 +1922,6 @@ class TestCourseDetail(TestCase): self.assertNotIn('message', response.context) self.assertTemplateUsed(response, 'yaksh/course_detail.html') - def test_course_detail_denies_anonymous(self): """ If not logged in redirect to login page diff --git a/yaksh/views.py b/yaksh/views.py index 71b4abe..61d2b5b 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -1856,49 +1856,54 @@ def upload_users(request, course_id): if 'csv_file' not in request.FILES: context['message'] = "Please upload a CSV file." return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) + context_instance=ci) csv_file = request.FILES['csv_file'] - if not is_csv(csv_file): + is_csv_file, dialect = is_csv(csv_file) + if not is_csv_file: context['message'] = "The file uploaded is not a CSV file." return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) - headers = {'firstname':'', 'lastname':'', 'email':''} - reader = csv.DictReader(csv_file.read().decode('utf-8').splitlines()) + context_instance=ci) + headers = {'firstname': '', 'lastname': '', 'email': ''} + try: + reader = csv.DictReader(csv_file.read().decode('utf-8').splitlines(), + dialect=dialect) + except TypeError: + context['message'] = "Bad CSV file" + return my_render_to_response('yaksh/course_detail.html', context, + context_instance=ci) if not headers_present(reader, headers): context['message'] = "The CSV file does not contain the required headers" return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) + context_instance=ci) context['upload_details'] = _read_user_csv(reader, headers, course) return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) + context_instance=ci) def _read_user_csv(reader, headers, course): upload_details = ["Upload Summary:"] - counter = 0; + counter = 0 + add_users = [] for row in reader: counter += 1 email, first_name, last_name = map(str.strip, [row[headers['email']], - row[headers['firstname']], row[headers['lastname']]]) + row[headers['firstname']], + row[headers['lastname']]]) if not email or not first_name or not last_name: upload_details.append("{0} -- Missing Values".format(counter)) continue - user = User.objects.filter(email=email) - if user.exists(): - upload_details.append("{0} -- {1} -- Email Already Exists".format( - counter, email)) + if User.objects.filter(Q(username=email) | Q(email=email)).exists(): + upload_details.append("{0} -- {1} -- Email or Username Already \ + Exists".format(counter, email)) else: - try: - user = User.objects.create_user(username=email, password=email, - email=email, first_name=first_name, last_name=last_name) - except IntegrityError: - upload_details.append("{0} -- {1} -- User Already Exists".format( - counter, email)) - else: - Profile.objects.create(user=user, is_email_verified=True) - course.students.add(user) - upload_details.append("{0} -- {1} -- User Added Successfully".format( - counter, email)) + user = User.objects.create_user(username=email, password=email, + email=email, first_name=first_name, + last_name=last_name) + Profile.objects.create(user=user, is_email_verified=True) + add_users.append(user) + upload_details.append("{0} -- {1} -- User Added Successfully".format( + counter, email)) + course.students.add(*add_users) if counter == 0: upload_details.append("No rows in the CSV file") return upload_details |