Commit 4ebbf87e95bb73d6afa51750e17616ddffe236b9
1 parent
af1350ae
Exists in
master
and in
3 other branches
distinct amount of views in resources and amount of views in resource is now co…
…rrect, added blank tag as well as removed duplicates from form
Showing
7 changed files
with
129 additions
and
51 deletions
Show diff stats
file_link/views.py
... | ... | @@ -21,7 +21,7 @@ from .models import FileLink |
21 | 21 | class DownloadFile(LoginRequiredMixin, LogMixin, generic.DetailView): |
22 | 22 | log_component = 'resources' |
23 | 23 | log_action = 'view' |
24 | - log_resource = 'file_link' | |
24 | + log_resource = 'filelink' | |
25 | 25 | log_context = {} |
26 | 26 | |
27 | 27 | login_url = reverse_lazy("users:login") |
... | ... | @@ -63,9 +63,9 @@ class DownloadFile(LoginRequiredMixin, LogMixin, generic.DetailView): |
63 | 63 | self.log_context['topic_id'] = file_link.topic.id |
64 | 64 | self.log_context['topic_name'] = file_link.topic.name |
65 | 65 | self.log_context['topic_slug'] = file_link.topic.slug |
66 | - self.log_context['file_link_id'] = file_link.id | |
67 | - self.log_context['file_link_name'] = file_link.name | |
68 | - self.log_context['file_link_slug'] = file_link.slug | |
66 | + self.log_context['filelink_id'] = file_link.id | |
67 | + self.log_context['filelink_name'] = file_link.name | |
68 | + self.log_context['filelink_slug'] = file_link.slug | |
69 | 69 | |
70 | 70 | super(DownloadFile, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) |
71 | 71 | |
... | ... | @@ -74,7 +74,7 @@ class DownloadFile(LoginRequiredMixin, LogMixin, generic.DetailView): |
74 | 74 | class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): |
75 | 75 | log_component = 'resources' |
76 | 76 | log_action = 'create' |
77 | - log_resource = 'file_link' | |
77 | + log_resource = 'filelink' | |
78 | 78 | log_context = {} |
79 | 79 | |
80 | 80 | login_url = reverse_lazy("users:login") |
... | ... | @@ -163,9 +163,9 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): |
163 | 163 | self.log_context['topic_id'] = self.object.topic.id |
164 | 164 | self.log_context['topic_name'] = self.object.topic.name |
165 | 165 | self.log_context['topic_slug'] = self.object.topic.slug |
166 | - self.log_context['file_link_id'] = self.object.id | |
167 | - self.log_context['file_link_name'] = self.object.name | |
168 | - self.log_context['file_link_slug'] = self.object.slug | |
166 | + self.log_context['filelink_id'] = self.object.id | |
167 | + self.log_context['filelink_name'] = self.object.name | |
168 | + self.log_context['filelink_slug'] = self.object.slug | |
169 | 169 | |
170 | 170 | super(CreateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) |
171 | 171 | |
... | ... | @@ -192,7 +192,7 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): |
192 | 192 | class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView): |
193 | 193 | log_component = 'resources' |
194 | 194 | log_action = 'update' |
195 | - log_resource = 'file_link' | |
195 | + log_resource = 'filelink' | |
196 | 196 | log_context = {} |
197 | 197 | |
198 | 198 | login_url = reverse_lazy("users:login") |
... | ... | @@ -277,9 +277,9 @@ class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView): |
277 | 277 | self.log_context['topic_id'] = self.object.topic.id |
278 | 278 | self.log_context['topic_name'] = self.object.topic.name |
279 | 279 | self.log_context['topic_slug'] = self.object.topic.slug |
280 | - self.log_context['file_link_id'] = self.object.id | |
281 | - self.log_context['file_link_name'] = self.object.name | |
282 | - self.log_context['file_link_slug'] = self.object.slug | |
280 | + self.log_context['filelink_id'] = self.object.id | |
281 | + self.log_context['filelink_name'] = self.object.name | |
282 | + self.log_context['filelink_slug'] = self.object.slug | |
283 | 283 | |
284 | 284 | super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) |
285 | 285 | |
... | ... | @@ -306,7 +306,7 @@ class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView): |
306 | 306 | class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView): |
307 | 307 | log_component = 'resources' |
308 | 308 | log_action = 'delete' |
309 | - log_resource = 'file_link' | |
309 | + log_resource = 'filelink' | |
310 | 310 | log_context = {} |
311 | 311 | |
312 | 312 | login_url = reverse_lazy("users:login") |
... | ... | @@ -337,9 +337,9 @@ class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView): |
337 | 337 | self.log_context['topic_id'] = self.object.topic.id |
338 | 338 | self.log_context['topic_name'] = self.object.topic.name |
339 | 339 | self.log_context['topic_slug'] = self.object.topic.slug |
340 | - self.log_context['file_link_id'] = self.object.id | |
341 | - self.log_context['file_link_name'] = self.object.name | |
342 | - self.log_context['file_link_slug'] = self.object.slug | |
340 | + self.log_context['filelink_id'] = self.object.id | |
341 | + self.log_context['filelink_name'] = self.object.name | |
342 | + self.log_context['filelink_slug'] = self.object.slug | |
343 | 343 | |
344 | 344 | super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) |
345 | 345 | ... | ... |
pdf_file/views.py
... | ... | @@ -23,7 +23,7 @@ class ViewPDFFile(LoginRequiredMixin, LogMixin, generic.TemplateView): |
23 | 23 | template_name='pdf_file/view.html' |
24 | 24 | log_component = 'resources' |
25 | 25 | log_action = 'view' |
26 | - log_resource = 'pdf_file' | |
26 | + log_resource = 'pdffile' | |
27 | 27 | log_context = {} |
28 | 28 | def dispatch(self, request, *args, **kwargs): |
29 | 29 | slug = self.kwargs.get('slug', '') |
... | ... | @@ -52,9 +52,9 @@ class ViewPDFFile(LoginRequiredMixin, LogMixin, generic.TemplateView): |
52 | 52 | self.log_context['topic_id'] = pdf_file.topic.id |
53 | 53 | self.log_context['topic_name'] = pdf_file.topic.name |
54 | 54 | self.log_context['topic_slug'] = pdf_file.topic.slug |
55 | - self.log_context['pdf_id'] = pdf_file.id | |
56 | - self.log_context['pdf_name'] = pdf_file.name | |
57 | - self.log_context['pdf_slug'] = pdf_file.slug | |
55 | + self.log_context['pdffile_id'] = pdf_file.id | |
56 | + self.log_context['pdffile_name'] = pdf_file.name | |
57 | + self.log_context['pdffile_slug'] = pdf_file.slug | |
58 | 58 | |
59 | 59 | super(ViewPDFFile, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) |
60 | 60 | |
... | ... | @@ -87,6 +87,7 @@ class PDFFileCreateView(LoginRequiredMixin, LogMixin , generic.CreateView): |
87 | 87 | login_url = reverse_lazy("users:login") |
88 | 88 | redirect_field_name = 'next' |
89 | 89 | |
90 | + log_resource = 'pdffile' | |
90 | 91 | |
91 | 92 | def dispatch(self, request, *args, **kwargs): |
92 | 93 | slug = self.kwargs.get('slug', '') |
... | ... | @@ -168,9 +169,9 @@ class PDFFileCreateView(LoginRequiredMixin, LogMixin , generic.CreateView): |
168 | 169 | self.log_context['topic_id'] = self.object.topic.id |
169 | 170 | self.log_context['topic_name'] = self.object.topic.name |
170 | 171 | self.log_context['topic_slug'] = self.object.topic.slug |
171 | - self.log_context['pdf_file_id'] = self.object.id | |
172 | - self.log_context['pdf_file_name'] = self.object.name | |
173 | - self.log_context['pdf_file_slug'] = self.object.slug | |
172 | + self.log_context['pdffile_id'] = self.object.id | |
173 | + self.log_context['pdffile_name'] = self.object.name | |
174 | + self.log_context['pdffile_slug'] = self.object.slug | |
174 | 175 | |
175 | 176 | super(PDFFileCreateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) |
176 | 177 | |
... | ... | @@ -198,7 +199,7 @@ class PDFFileCreateView(LoginRequiredMixin, LogMixin , generic.CreateView): |
198 | 199 | class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView): |
199 | 200 | log_component = 'resources' |
200 | 201 | log_action = 'update' |
201 | - log_resource = 'pdf_file' | |
202 | + log_resource = 'pdffile' | |
202 | 203 | log_context = {} |
203 | 204 | |
204 | 205 | login_url = reverse_lazy("users:login") |
... | ... | @@ -283,9 +284,9 @@ class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView): |
283 | 284 | self.log_context['topic_id'] = self.object.topic.id |
284 | 285 | self.log_context['topic_name'] = self.object.topic.name |
285 | 286 | self.log_context['topic_slug'] = self.object.topic.slug |
286 | - self.log_context['pdf_file_id'] = self.object.id | |
287 | - self.log_context['pdf_file_name'] = self.object.name | |
288 | - self.log_context['pdf_file_slug'] = self.object.slug | |
287 | + self.log_context['pdffile_id'] = self.object.id | |
288 | + self.log_context['pdffile_name'] = self.object.name | |
289 | + self.log_context['pdffile_slug'] = self.object.slug | |
289 | 290 | |
290 | 291 | super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) |
291 | 292 | |
... | ... | @@ -343,9 +344,9 @@ class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView): |
343 | 344 | self.log_context['topic_id'] = self.object.topic.id |
344 | 345 | self.log_context['topic_name'] = self.object.topic.name |
345 | 346 | self.log_context['topic_slug'] = self.object.topic.slug |
346 | - self.log_context['pdf_file_id'] = self.object.id | |
347 | - self.log_context['pdf_file_name'] = self.object.name | |
348 | - self.log_context['pdf_file_slug'] = self.object.slug | |
347 | + self.log_context['pdffile_id'] = self.object.id | |
348 | + self.log_context['pdffile_name'] = self.object.name | |
349 | + self.log_context['pdffile_slug'] = self.object.slug | |
349 | 350 | |
350 | 351 | super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) |
351 | 352 | ... | ... |
... | ... | @@ -0,0 +1,30 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10.4 on 2017-03-21 00:55 | |
3 | +from __future__ import unicode_literals | |
4 | + | |
5 | +from django.conf import settings | |
6 | +from django.db import migrations, models | |
7 | +import django.db.models.deletion | |
8 | + | |
9 | + | |
10 | +class Migration(migrations.Migration): | |
11 | + | |
12 | + dependencies = [ | |
13 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
14 | + ('reports', '0001_initial'), | |
15 | + ] | |
16 | + | |
17 | + operations = [ | |
18 | + migrations.CreateModel( | |
19 | + name='ReportXLS', | |
20 | + fields=[ | |
21 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
22 | + ('xls_data', models.TextField()), | |
23 | + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), | |
24 | + ], | |
25 | + options={ | |
26 | + 'verbose_name': 'ReportCSV', | |
27 | + 'verbose_name_plural': 'ReportCSVs', | |
28 | + }, | |
29 | + ), | |
30 | + ] | ... | ... |
reports/models.py
... | ... | @@ -12,4 +12,17 @@ class ReportCSV(models.Model): |
12 | 12 | |
13 | 13 | def __str__(self): |
14 | 14 | pass |
15 | + | |
16 | + | |
17 | +class ReportXLS(models.Model): | |
18 | + | |
19 | + user = models.ForeignKey(User) | |
20 | + xls_data = models.TextField() | |
21 | + | |
22 | + class Meta: | |
23 | + verbose_name = "ReportCSV" | |
24 | + verbose_name_plural = "ReportCSVs" | |
25 | + | |
26 | + def __str__(self): | |
27 | + pass | |
15 | 28 | |
16 | 29 | \ No newline at end of file | ... | ... |
reports/templates/reports/view.html
... | ... | @@ -65,7 +65,7 @@ |
65 | 65 | <ul id="report-info"> |
66 | 66 | <li> {{data.values|length}} {% trans "register(s)" %} </li> |
67 | 67 | <li> |
68 | - <a href="{% url 'subjects:reports:download_report' %}?{{csv_data}}"><i class="fa fa-download" aria-hidden="true"></i> {% trans "Interactions Data" %}</a> | |
68 | + <a href="{% url 'subjects:reports:download_report_csv' %}"><i class="fa fa-download" aria-hidden="true"></i> {% trans "Interactions Data" %}</a> | |
69 | 69 | |
70 | 70 | |
71 | 71 | </li> | ... | ... |
reports/urls.py
... | ... | @@ -7,5 +7,5 @@ urlpatterns = [ |
7 | 7 | url(r'^view/interactions/$', views.ViewReportView.as_view(), name='view_report'), |
8 | 8 | url(r'^get/resources/$', views.get_resources, name='get_resource_and_tags'), |
9 | 9 | url(r'^get/tags/$', views.get_tags, name='get_tags'), |
10 | - url(r'^post/download_report/$', views.download_report, name="download_report"), | |
10 | + url(r'^post/download_report/$', views.download_report_csv, name="download_report_csv"), | |
11 | 11 | ] |
12 | 12 | \ No newline at end of file | ... | ... |
reports/views.py
... | ... | @@ -11,14 +11,14 @@ import django.views.generic as generic |
11 | 11 | from mural.models import SubjectPost, Comment, MuralVisualizations |
12 | 12 | from django.db.models import Q |
13 | 13 | from django.contrib.auth.mixins import LoginRequiredMixin |
14 | -from datetime import datetime, date | |
14 | +from datetime import datetime, date, timedelta | |
15 | 15 | from subjects.models import Subject, Tag |
16 | 16 | from .forms import CreateInteractionReportForm, ResourceAndTagForm, BaseResourceAndTagFormset |
17 | 17 | from log.models import Log |
18 | 18 | from topics.models import Resource, Topic |
19 | 19 | from collections import OrderedDict |
20 | 20 | from django.forms import formset_factory |
21 | -from .models import ReportCSV | |
21 | +from .models import ReportCSV, ReportXLS | |
22 | 22 | import pandas as pd |
23 | 23 | |
24 | 24 | class ReportView(LoginRequiredMixin, generic.FormView): |
... | ... | @@ -143,32 +143,47 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
143 | 143 | |
144 | 144 | #this is to save the csv for further download |
145 | 145 | df = pd.DataFrame.from_dict(context['data'], orient='index') |
146 | - | |
147 | 146 | df.columns = context['header'] |
148 | 147 | #so it does not exist more than one report CSV available for that user to download |
149 | 148 | if ReportCSV.objects.filter(user= self.request.user).count() > 0: |
150 | 149 | report = ReportCSV.objects.get(user=self.request.user) |
151 | 150 | report.delete() |
152 | 151 | |
153 | - | |
152 | + | |
154 | 153 | report = ReportCSV(user= self.request.user, csv_data = df.to_csv()) |
155 | 154 | report.save() |
156 | 155 | |
156 | + #for excel files | |
157 | + """ if ReportXLS.objects.filter(user= self.request.user).count() > 0: | |
158 | + report = ReportXLS.objects.get(user=self.request.user) | |
159 | + report.delete() | |
160 | + | |
161 | + df.drop(df.columns[[0]], axis=1, inplace=True) | |
162 | + writer = pd.ExcelWriter('pandas_simple.xlsx') | |
163 | + report = ReportXLS(user= self.request.user, xls_data = df.to_excel(writer)) | |
164 | + report.save()""" | |
165 | + | |
166 | + | |
157 | 167 | return context |
158 | 168 | |
159 | 169 | def get_mural_data(self, subject, init_date, end_date, resources_id, tags_id): |
160 | 170 | data = {} |
161 | 171 | students = subject.students.all() |
162 | - formats = ["%d/%m/%Y", "%m/%d/%Y"] #so it accepts english and portuguese date formats | |
172 | + formats = ["%d/%m/%Y", "%m/%d/%Y", "%Y-%m-%d"] #so it accepts english and portuguese date formats | |
163 | 173 | for fmt in formats: |
164 | 174 | try: |
165 | - init_date = datetime.strptime(init_date, fmt) | |
166 | - end_date = datetime.strptime(end_date, fmt) | |
175 | + init_date = datetime.strptime(init_date, fmt).date() | |
176 | + end_date = datetime.strptime(end_date, fmt).date() | |
177 | + | |
167 | 178 | except ValueError: |
168 | 179 | pass |
169 | 180 | |
170 | 181 | header = ['User'] |
171 | - | |
182 | + | |
183 | + #I use this so the system can gather data up to end_date 11h59 p.m. | |
184 | + end_date = end_date + timedelta(days=1) | |
185 | + | |
186 | + | |
172 | 187 | #For each student in the subject |
173 | 188 | for student in students: |
174 | 189 | data[student] = [] |
... | ... | @@ -226,7 +241,7 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
226 | 241 | |
227 | 242 | #VAR08 through VAR_019 of documenttation: |
228 | 243 | if len(resources_id) > 0: |
229 | - resources_data = self.get_resources_and_tags_data(resources_id, tags_id, student, subject) | |
244 | + resources_data = self.get_resources_and_tags_data(resources_id, tags_id, student, subject, init_date, end_date) | |
230 | 245 | for key, value in resources_data.items(): |
231 | 246 | interactions[key] = value |
232 | 247 | |
... | ... | @@ -268,12 +283,26 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
268 | 283 | header.append(key) |
269 | 284 | return data, header |
270 | 285 | |
271 | - def get_resources_and_tags_data(self, resources, tags, student, subject): | |
272 | - data = {} | |
286 | + def get_resources_and_tags_data(self, resources_types, tags, student, subject, init_date, end_date): | |
287 | + data = OrderedDict() | |
273 | 288 | |
274 | - for i in range(len(resources)): | |
275 | - data[str(resources[i]) + " with tag " + Tag.objects.get(id=int(tags[i])).name] = Log.objects.filter(action="view", resource=resources[i].lower(), | |
276 | - user_id = student.id, context__contains = {'subject_id': subject.id}).count() | |
289 | + for i in range(len(resources_types)): | |
290 | + | |
291 | + resources = Resource.objects.select_related(resources_types[i].lower()).filter(tags__in = tags, topic__in=subject.topic_subject.all()) | |
292 | + distinct_resources = 0 | |
293 | + total_count = 0 | |
294 | + for resource in resources: | |
295 | + count = Log.objects.filter(action="view", resource=resources_types[i].lower(), | |
296 | + user_id = student.id, context__contains = {'subject_id': subject.id, | |
297 | + resources_types[i].lower()+'_id': resource.id}, datetime__range=(init_date, end_date)).count() | |
298 | + if count > 0: | |
299 | + distinct_resources += 1 | |
300 | + total_count += count | |
301 | + | |
302 | + data[str(resources_types[i]) + " with tag " + Tag.objects.get(id=int(tags[i])).name] = total_count | |
303 | + data["distintic " + str(resources_types[i]) + " with tag " + Tag.objects.get(id=int(tags[i])).name] = distinct_resources | |
304 | + """data["distinct" + str(resources[i]) + " with tag " + Tag.objects.get(id=int(tags[i])).name] = Log.objects.filter(action="view", resource=resources[i].lower(), | |
305 | + user_id = student.id, context__contains = {'subject_id': subject.id}).distinct().count()""" | |
277 | 306 | |
278 | 307 | return data |
279 | 308 | |
... | ... | @@ -317,27 +346,32 @@ def get_tags(request): |
317 | 346 | resource_type = request.GET['resource_class_name'] |
318 | 347 | subject = Subject.objects.get(id=request.GET['subject_id']) |
319 | 348 | topic_choice = request.GET["topic_choice"] |
349 | + | |
350 | + #Have to fix this to accept translated options | |
320 | 351 | if topic_choice.lower() == "all" or topic_choice.lower() == "todos": |
321 | 352 | topics = subject.topic_subject.all() |
322 | 353 | else: |
323 | 354 | topics = [Topic.objects.get(id=int(topic_choice))] |
324 | 355 | data = {} |
325 | - tags = [] | |
356 | + tags = set() | |
326 | 357 | for topic in topics: |
327 | 358 | resource_set = Resource.objects.select_related(resource_type.lower()).filter(topic = topic) |
328 | 359 | |
329 | 360 | for resource in resource_set: |
330 | 361 | if resource._my_subclass == resource_type.lower(): |
331 | 362 | for tag in resource.tags.all(): |
332 | - tags.append(tag) | |
333 | - | |
363 | + if tag.name != "": | |
364 | + tags.add(tag) | |
365 | + | |
334 | 366 | |
335 | - | |
367 | + #adding empty tag for the purpose of giving the user this option for adicional behavior | |
368 | + tags = list(tags) | |
369 | + tags.append(Tag(name="")) | |
336 | 370 | data['tags'] = [ {'id':tag.id, 'name':tag.name} for tag in tags] |
337 | 371 | return JsonResponse(data) |
338 | 372 | |
339 | 373 | |
340 | -def download_report(request): | |
374 | +def download_report_csv(request): | |
341 | 375 | report = ReportCSV.objects.get(user=request.user) |
342 | 376 | |
343 | 377 | response = HttpResponse(report.csv_data,content_type='text/csv') | ... | ... |