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') | ... | ... |