Skip to content

Commit dd6c9f4

Browse files
committed
Fix utf8 encoding for CSV uploads
1 parent 6ca0fe4 commit dd6c9f4

File tree

1 file changed

+53
-27
lines changed

1 file changed

+53
-27
lines changed

grants/views/bulk_load.py

+53-27
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,23 @@ def post(self, request):
2727
else:
2828
csv_obj = UploadedCSV.objects.get(pk=request.POST["csv_id"])
2929
# We always get a CSV file - parse it.
30-
reader = csv.reader([x + "\n" for x in str(csv_obj.csv).split("\n")])
30+
reader = csv.reader([x + "\n" for x in csv_obj.csv.decode("utf8").split("\n")])
3131
rows = list(reader)
3232
headers = rows[0]
3333
column_choices = [("", "---")] + list(enumerate(headers))
3434
# Make form with question mapping fields
3535
fields = collections.OrderedDict(
36-
(name, forms.ChoiceField(choices=column_choices, required=required, label=label))
36+
(
37+
name,
38+
forms.ChoiceField(
39+
choices=column_choices, required=required, label=label
40+
),
41+
)
3742
for name, required, label in self.get_targets()
3843
)
3944
form_input = {"csv_id": csv_obj.pk}
4045
form_input.update(request.POST.items())
41-
form = type("BulkLoadMapForm", (BulkLoadMapBaseForm, ), fields)(form_input)
46+
form = type("BulkLoadMapForm", (BulkLoadMapBaseForm,), fields)(form_input)
4247
# Did they submit mappings for all questions? If not, show form
4348
if form.is_valid():
4449
# Save and import!
@@ -57,15 +62,19 @@ def post(self, request):
5762
except Exception as e:
5863
errors.append((i, row, e))
5964
csv_obj.delete()
60-
return self.render_to_response({
61-
"successful": successful,
62-
"errors": errors,
63-
})
65+
return self.render_to_response(
66+
{
67+
"successful": successful,
68+
"errors": errors,
69+
}
70+
)
6471
else:
6572
# Show mapping form
66-
return self.render_to_response({
67-
"form": form,
68-
})
73+
return self.render_to_response(
74+
{
75+
"form": form,
76+
}
77+
)
6978

7079

7180
class BulkLoadApplicants(BulkLoader, TemplateView):
@@ -88,23 +97,27 @@ def get_targets(self):
8897
("timestamp", False, "Timestamp"),
8998
]
9099
for question in self.program.questions.all():
91-
targets.append((
92-
"q%s" % question.id,
93-
True,
94-
question.question,
95-
))
100+
targets.append(
101+
(
102+
"q%s" % question.id,
103+
True,
104+
question.question,
105+
)
106+
)
96107
return targets
97108

98109
def process_row(self, row, target_map):
99110
if self.program.duplicate_emails:
100111
applicant = None
101112
else:
102-
applicant = Applicant.objects.filter(program=self.program, email=row[target_map["email"]]).first()
113+
applicant = Applicant.objects.filter(
114+
program=self.program, email=row[target_map["email"]]
115+
).first()
103116
if not applicant:
104117
applicant = Applicant(
105-
program = self.program,
106-
name = row[target_map["name"]],
107-
email = row[target_map["email"]],
118+
program=self.program,
119+
name=row[target_map["name"]],
120+
email=row[target_map["email"]],
108121
)
109122
else:
110123
applicant.name = row[target_map["name"]]
@@ -116,7 +129,9 @@ def process_row(self, row, target_map):
116129
if target_map.get("timestamp", None):
117130
for time_format in self.time_formats:
118131
try:
119-
applicant.applied = datetime.datetime.strptime(row[target_map["timestamp"]], time_format)
132+
applicant.applied = datetime.datetime.strptime(
133+
row[target_map["timestamp"]], time_format
134+
)
120135
except ValueError:
121136
pass
122137
applicant.save()
@@ -126,22 +141,32 @@ def process_row(self, row, target_map):
126141
raw_answer = row[target_map[key]]
127142
question = self.program.questions.get(pk=key.lstrip("q"))
128143
if question.type == "boolean":
129-
answer = str(not any((raw_answer.lower().strip() == no_word) for no_word in ("no", "false", "off", "", "0")))
144+
answer = str(
145+
not any(
146+
(raw_answer.lower().strip() == no_word)
147+
for no_word in ("no", "false", "off", "", "0")
148+
)
149+
)
130150
elif question.type == "integer":
131151
if not raw_answer.strip():
132152
answer = None
133153
else:
134154
try:
135155
answer = str(int(raw_answer.strip()))
136156
except ValueError:
137-
raise ValueError("Invalid integer value for question %s: %s" % (question.question, raw_answer))
157+
raise ValueError(
158+
"Invalid integer value for question %s: %s"
159+
% (question.question, raw_answer)
160+
)
138161
else:
139162
answer = raw_answer
140-
answer_obj = Answer.objects.filter(applicant=applicant, question=question).first()
163+
answer_obj = Answer.objects.filter(
164+
applicant=applicant, question=question
165+
).first()
141166
if not answer_obj:
142167
answer_obj = Answer(
143-
applicant = applicant,
144-
question = question,
168+
applicant=applicant,
169+
question=question,
145170
)
146171
answer_obj.answer = answer or ""
147172
answer_obj.save()
@@ -154,7 +179,6 @@ class BulkLoadScores(BulkLoader, TemplateView):
154179

155180
template_name = "program-bulk-scores.html"
156181

157-
158182
def get_targets(self):
159183
return [
160184
("email", True, "Email"),
@@ -165,7 +189,9 @@ def get_targets(self):
165189
def process_row(self, row, target_map):
166190
applicant = Applicant.objects.get(email=row[target_map["email"]])
167191

168-
score = Score.objects.get_or_create(applicant=applicant, user=self.request.user)[0]
192+
score = Score.objects.get_or_create(
193+
applicant=applicant, user=self.request.user
194+
)[0]
169195
score_value = row[target_map["score"]]
170196
try:
171197
score.score = float(score_value)

0 commit comments

Comments
 (0)