Django csv example 1 ¶
Contents
views_report.py ¶
1"""Gestion des rapports (reports) pour les transactions mensuelles.
2
3
4Thanks to:
5
6- https://simpleisbetterthancomplex.com/tutorial/2016/07/29/how-to-export-to-excel.html
7
8
9def export_users_csv(request):
10 response = HttpResponse(content_type="text/csv")
11 response["Content-Disposition"] = 'attachment; filename="users.csv"'
12
13 writer = csv.writer(response)
14 writer.writerow(["Username", "First name", "Last name", "Email address"])
15
16 users = User.objects.all().values_list(
17 "username", "first_name", "last_name", "email"
18 )
19 for user in users:
20 writer.writerow(user)
21
22 return response
23
24"""
25# http://ianalexandr.com/blog/getting-started-with-django-logging-in-5-minutes.html
26import csv
27import logging
28
29import pendulum
30from agence.models import Agence
31from django.conf import settings
32from django.contrib.auth.decorators import login_required
33from django.core.paginator import EmptyPage
34from django.core.paginator import PageNotAnInteger
35from django.core.paginator import Paginator
36from django.db.models import Q
37from django.db.models import Sum
38from django.http import HttpResponse
39from django.http import HttpResponseRedirect
40from django.http.request import HttpRequest
41from django.http.request import QueryDict
42from django.shortcuts import get_object_or_404
43from django.shortcuts import render
44from django.urls import reverse
45from django.utils import timezone
46from django.utils.translation import ugettext_lazy as _
47from stats.models.models_day import StatsDay
48from stats.models.models_day_agence import StatsDayAgence
49from stats.models.models_day_agence import StatsMonthAgence
50from stats.models.models_global_counters import StatsGlobalCounters
51from stats.models.models_mixins import EnumTypeSums
52from stats.models.models_mixins import InfosTransactionMixin
53from users.models import User
54
55from .forms import FormFiltreReports
56from .models import LogTransactionNotariale
57from .serializers import LogTransactionNotarialeSerializer
58from .views import get_america_bogota_date_from_get_request
59from .views import get_time_from_america_bogota
60
61# https://docs.djangoproject.com/en/dev/topics/settings/#using-settings-in-python-code
62
63# Get an instance of a logger
64logger = logging.getLogger(__name__)
65
66
67__all__ = ("VueReportGeneralInfoMonth",)
68
69
70def ReadGetVueReportGeneralInfoMonth(
71 request: HttpRequest,
72) -> (pendulum.datetime, FormFiltreReports):
73 # GET: c'est quand on pointe sur la page directement ou que l'on
74 # utilise paginator
75 logger.info(f"request={request.GET}")
76
77 # Est-ce qu'il y a un filtre sur la date from_date ?
78 from_date = get_america_bogota_date_from_get_request(request, "from_date")
79 if from_date is None:
80 # on initialise la date 12 mois avant
81 # from_date = pendulum.now("America/Bogota").add(months=-12)
82 from_date = pendulum.now("America/Bogota").add(months=-1)
83
84 # https://docs.djangoproject.com/en/dev/ref/forms/api/#dynamic-initial-values
85 form_filtres_reports = FormFiltreReports(
86 initial={
87 "date_from": from_date,
88 "export_excel": False,
89 }
90 )
91
92 # logger.info(f"ReadGetVueGrapheStatsDayAgence() form_filtre_reports:{form_filtre_reports}")
93
94 return from_date, form_filtres_reports
95
96
97def ReadPostVueReportGeneralInfoMonth(
98 request: HttpRequest,
99) -> (pendulum.datetime, FormFiltreReports):
100 # POST c'est quand l'utilisateur appuie sur le bouton 'Appliquer'
101 # A revoir car "Search forms that are idempotent should use the GET method"
102 # p. 142, chapitre 11 "Form fundamentals" Two scoops of Django
103 logger.info(f"POST={request.POST}")
104 if "btn_form_filtre" in request.POST:
105 # Instanciation du formulaire
106 form_filtre_reports = FormFiltreReports(request.POST)
107 if form_filtre_reports.is_valid():
108 # indispensable pour avoir le tableau 'cleaned_data'
109 # qui remet les dates anglaises en place:
110 date_naive = form_filtre_reports.cleaned_data["date_from"]
111 date_from_colombia = get_time_from_america_bogota(date_naive)
112 logger.info("Colombia Date :{date_from_colombia=}")
113
114 return date_from_colombia, form_filtre_reports
115
116
117@login_required(login_url="home")
118def VueReportGeneralInfoMonth(
119 request: HttpRequest,
120 template_name="log_transaction_notariale/report_choose_date.html",
121) -> HttpResponse:
122 """Production du rapport General info report month ("Informe general")
123
124 Dans un premier temps on choisit la date et ensuite on exporte le fichier csv.
125
126 - https://simpleisbetterthancomplex.com/tutorial/2016/07/29/how-to-export-to-excel.html
127 """
128 logger.info("Begin VueReportGeneralInfoMonth()")
129 form_filtre_reports = None
130 if request.method == "POST":
131 start_date, form_filtre_reports = ReadPostVueReportGeneralInfoMonth(request)
132 start_date = start_date.start_of("month")
133 end_date = start_date.end_of("month")
134 logger.info(f"{start_date=} => {end_date=}")
135
136 format_year_month = f"{start_date.strftime('%Y-%m')}"
137 filename = f"{format_year_month}_Informe_generale.csv"
138 response = HttpResponse(content_type="text/csv")
139 response["Content-Disposition"] = f"attachment; filename={filename}"
140
141 writer = csv.writer(response)
142 entete_date = f"Fecha ({format_year_month})"
143 writer.writerow([entete_date, "Con biometria", "Sin biometria"])
144 current_day = start_date
145 while current_day <= end_date:
146 end_day = current_day.add(days=1)
147 nb_transaction_days = 0
148 nb_transactions = 0
149 transactions_day = LogTransactionNotariale.objects.filter(
150 date_transaction__range=[current_day, end_day]
151 )
152 nb_transactions_avec_biometrie = transactions_day.filter(
153 match_rnec_enabled=1
154 ).count()
155 nb_transactions_sans_biometrie = transactions_day.filter(
156 match_rnec_enabled=0
157 ).count()
158 format_current_day = current_day.strftime("%Y-%m-%d")
159 # logger.info(
160 # f"{format_current_day};{nb_transactions_avec_biometrie};{nb_transactions_sans_biometrie}"
161 # )
162 logger.info(f"\n{current_day=}\nSQL query:\n{str(transactions_day.query)}")
163 writer.writerow(
164 (
165 format_current_day,
166 nb_transactions_avec_biometrie,
167 nb_transactions_sans_biometrie,
168 )
169 )
170 current_day = end_day
171
172 return response
173
174 elif request.method == "GET":
175 from_date, form_filtre_reports = ReadGetVueReportGeneralInfoMonth(request)
176 context_commentaire = "general info report month"
177 return render(
178 request,
179 template_name,
180 context={
181 "form_filtre_reports": form_filtre_reports,
182 "url_post": reverse(
183 "log_transaction_notariale:report_general_info_month"
184 ),
185 # Filtres on emploie "0" car None n'est pas reconnu par
186 # le langage de template Django
187 "from_date": "0" if from_date is None else from_date,
188 "commentaire": context_commentaire,
189 },
190 )
191
192
193@login_required(login_url="home")
194def VueReportDetailedInfoDay(
195 request: HttpRequest,
196 template_name="log_transaction_notariale/report_choose_date.html",
197) -> HttpResponse:
198 """Detailed info report day ("Informe detallado")
199
200 Dans un premier temps on choisit la date et ensuite on exporte le fichier csv.
201
202 - https://simpleisbetterthancomplex.com/tutorial/2016/07/29/how-to-export-to-excel.html
203 """
204 logger.info("Begin VueReportDetailedInfoDay()")
205 form_filtre_reports = None
206 if request.method == "POST":
207 day_date, form_filtre_reports = ReadPostVueReportGeneralInfoMonth(request)
208 logger.info(f"{day_date=}")
209 format_day_date = f"{day_date.strftime('%Y-%m-%d')}"
210 filename = f"{format_day_date}_Informe_detallado.csv"
211 response = HttpResponse(content_type="text/csv")
212 response["Content-Disposition"] = f"attachment; filename={filename}"
213 writer = csv.writer(response)
214 writer.writerow(
215 [
216 "Codigo Notaria",
217 "#Total transacciones",
218 "#Cotejos Hit",
219 "#Cotejos No-Hit",
220 "Sin biometria",
221 ]
222 )
223 # tri par ordre descendant sur le nombre total de transactions, i.e du plus grand au plus petit
224 liste = StatsDayAgence.objects.filter(date=day_date).order_by(
225 "-nb_transactions"
226 )
227 logger.info(f"\n{day_date=}\nSQL query:\n{str(liste.query)}")
228 for i, t in enumerate(liste):
229 # logger.info(
230 # f"{t.agence.id_etude_notariale=} {t.nb_transactions=} HIT:{t.nb_global_match_rnec_ok} No-HIT:{t.nb_global_match_rnec_pb} Sans biométrie:{t.nb_match_rnec_disabled}"
231 # )
232 writer.writerow(
233 (
234 t.agence.id_etude_notariale,
235 t.nb_transactions,
236 t.nb_global_match_rnec_ok,
237 t.nb_global_match_rnec_pb,
238 t.nb_match_rnec_disabled,
239 )
240 )
241
242 return response
243
244 elif request.method == "GET":
245 from_date, form_filtre_reports = ReadGetVueReportGeneralInfoMonth(request)
246 context_commentaire = "detailed info report day"
247 return render(
248 request,
249 template_name,
250 context={
251 "form_filtre_reports": form_filtre_reports,
252 "url_post": reverse(
253 "log_transaction_notariale:report_detailed_info_day"
254 ),
255 # Filtres on emploie "0" car None n'est pas reconnu par
256 # le langage de template Django
257 "from_date": "0" if from_date is None else from_date,
258 "commentaire": context_commentaire,
259 },
260 )
261
262
263@login_required(login_url="home")
264def VueReportDetailedInfoMonth(
265 request: HttpRequest,
266 template_name="log_transaction_notariale/report_choose_date.html",
267) -> HttpResponse:
268 """Detailed info report month ("Informe detallado"):
269
270 Dans un premier temps on choisit la date et ensuite on exporte le fichier csv.
271
272 - https://simpleisbetterthancomplex.com/tutorial/2016/07/29/how-to-export-to-excel.html
273 """
274 logger.info("Begin VueReportDetailedInfoMonth()")
275 form_filtre_reports = None
276 if request.method == "POST":
277 month_date, form_filtre_reports = ReadPostVueReportGeneralInfoMonth(request)
278 logger.info(f"{month_date=}")
279 format_month_date = f"{month_date.strftime('%Y-%m')}"
280 filename = f"{format_month_date}_Informe_detallado.csv"
281 response = HttpResponse(content_type="text/csv")
282 response["Content-Disposition"] = f"attachment; filename={filename}"
283 writer = csv.writer(response)
284 writer.writerow(
285 [
286 "Codigo Notaria",
287 "#Total transacciones",
288 "#Cotejos Hit",
289 "#Cotejos No-Hit",
290 "Sin biometria",
291 ]
292 )
293 liste = StatsMonthAgence.objects.filter(
294 year=month_date.year, month=month_date.month
295 ).order_by("-nb_transactions")
296 logger.info(f"\nSQL query:\n{str(liste.query)}")
297 for i, t in enumerate(liste):
298 # logger.info(
299 # f"{t.agence.id_etude_notariale=} {t.nb_transactions=} HIT:{t.nb_global_match_rnec_ok} No-HIT:{t.nb_global_match_rnec_pb} Sans biométrie:{t.nb_match_rnec_disabled}"
300 # )
301 writer.writerow(
302 (
303 t.agence.id_etude_notariale,
304 t.nb_transactions,
305 t.nb_global_match_rnec_ok,
306 t.nb_global_match_rnec_pb,
307 t.nb_match_rnec_disabled,
308 )
309 )
310
311 return response
312
313 elif request.method == "GET":
314 from_date, form_filtre_reports = ReadGetVueReportGeneralInfoMonth(request)
315 context_commentaire = "detailed info report month"
316 return render(
317 request,
318 template_name,
319 context={
320 "form_filtre_reports": form_filtre_reports,
321 "url_post": reverse(
322 "log_transaction_notariale:report_detailed_info_month"
323 ),
324 # Filtres on emploie "0" car None n'est pas reconnu par
325 # le langage de template Django
326 "from_date": "0" if from_date is None else from_date,
327 "commentaire": context_commentaire,
328 },
329 )
report_choose_date.html ¶
1{% extends "base.html" %}
2{% load static %}
3{% load staticfiles %}
4{% load i18n %}
5{% load l10n %}
6{% load humanize %}
7{% load tz %}
8{% load helper_i18n_tags %}
9
10
11{% block stylesheet %}
12 <!-- CSS pour datetime picker -->
13 <link rel="stylesheet" href="{% static 'js/jquery.datetimepicker.min.css' %}">
14
15{% endblock %}
16
17{% block javascript_libraries %}
18 {{ block.super }}
19
20 <!-- datetime picker jQuery script -->
21 <!-- https://marcocecchetti.it/Post/Articolo/608 -->
22 <script src="{% static 'js/jquery.datetimepicker.full.js' %}"></script>
23
24{% endblock javascript_libraries %}
25
26{# Translators: Apparait dans le titre de la page (head title) #}
27{% block head_title %} {% trans "Liste des transactions notariales en Colombie" %} {% endblock %}
28
29
30{% block content %}
31
32
33<div class="panel-group" id="accordeon">
34 {# https://getbootstrap.com/components/#panels #}
35 <div class="panel panel-primary">
36 <div class="panel-heading">
37 <h4 class="panel-title">
38 <a data-toggle="collapse" data-parent="#accordeon" href="#caracteristiques">Choose date for {{ commentaire }}</a>
39 </h4>
40 </div>
41 <div id="caracteristiques" class="panel-collapse collapse in">
42 <div class="panel-body">
43 <div class="panel panel-default">
44 <div class="panel-body">
45 <form method="post" action="{{url_post }}" id="id_form"> {% csrf_token %}
46 {{ form_filtre_reports.non_field_errors }}
47 <div class="table-responsive table-condensed">
48 <table id="id_search_table" class="table table-striped table-bordered" width="100%">
49 <tbody>
50 <tr>
51 <td width="50%"> {{ form_filtre_reports.date_from.label_tag}} {{ form_filtre_reports.date_from }} </td>
52 </tr>
53 </tbody>
54 </table>
55 </div>
56 <input type="submit" name="btn_form_filtre" id="id_btn_form_filtre" value="Export csv file" class="btn btn-success btn-block" />
57 </form>
58 </div>
59 <div class="panel-footer">
60 </div>
61 </div>
62 </div>
63 </div>
64 </div>
65</div>
66
67
68{% endblock content %}
69
70{% block extra_js %}
71 <script type="text/javascript">
72
73 $(document).ready(function() {
74
75 $('#id_agence_notariale').select2();
76 $('#id_agence_notariale').on('change', function() {
77 {# https://openclassrooms.com/courses/un-site-web-dynamique-avec-jquery/jquery-et-les-evenements #}
78
79 $('#id_filtre_agence').prop("checked", true);
80 });
81 // langue française
82 $.datetimepicker.setLocale('fr');
83
84 {# https://jqueryui.com/datepicker/ #}
85 $('#id_date_from').datetimepicker(
86 {
87 // https://marcocecchetti.it/Post/Articolo/608
88 weeks: true,
89 rtl: false,
90 // formatTime:'H:i',
91 // formatDate:'d/m/Y',
92 format: 'd/m/Y',
93 // date
94 datepicker: true,
95 opened: false,
96 todayButton: true, // Show button "Go To Today"
97 defaultSelect: true, // Highlight the current date even if the input is empty
98 dayOfWeekStart : 1, // Start week DatePicker. Default Sunday=0.
99 yearStart: 2015, // année de début application
100 defaultDate: false,
101 // https://secure.php.net/manual/fr/function.date.php
102 maxDate:0, // today
103 minDate:'22.6.2015',formatDate:'d.m.Y',
104 weekends : [],
105 disabledDates : [],
106 // time
107 timepicker:false,
108 onClose: function( selectedDate ) {
109 $('#id_date_to' ).datetimepicker("option", "minDate", selectedDate );
110 }
111 }
112 );
113 $('#id_date_to').datetimepicker(
114 {
115 // https://marcocecchetti.it/Post/Articolo/608
116 weeks: true,
117 rtl: false,
118 // formatTime:'H:i',
119 // formatDate:'d/m/Y',
120 format: 'd/m/Y',
121 // date
122 datepicker: true,
123 opened: false,
124 todayButton: true, // Show button "Go To Today"
125 defaultSelect: true, // Highlight the current date even if the input is empty
126 dayOfWeekStart : 1, // Start week DatePicker. Default Sunday=0.
127 yearStart: 2015, // année de début application
128 defaultDate: false,
129 // https://secure.php.net/manual/fr/function.date.php
130 maxDate:0, // today
131 minDate:'22.6.2015',formatDate:'d.m.Y',
132 weekends : [],
133 disabledDates : [],
134 // time
135 timepicker:false,
136 onClose: function( selectedDate ) {
137 $('#id_date_from').datetimepicker("option", "maxDate", selectedDate );
138 }
139 }
140 );
141
142 $('#id_date_from').on('change', function() {
143 {# https://openclassrooms.com/courses/un-site-web-dynamique-avec-jquery/jquery-et-les-evenements #}
144
145 $('#id_filtre_date').prop("checked", true);
146 });
147
148 $('#id_date_to').on('change', function() {
149 {# https://openclassrooms.com/courses/un-site-web-dynamique-avec-jquery/jquery-et-les-evenements #}
150
151 $('#id_filtre_date').prop("checked", true);
152 });
153
154
155 function set_language_code(){
156 {# Lecture du code langage #}
157 {# https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes #}
158 var code_language = $('#id_language_code').val();
159 {# alert("code language" +code_language); #}
160 $.datetimepicker.setLocale('code_language');
161
162 // $('#id_date_from').datepicker("option", $.datepicker.regional[ code_language ] );
163 // $('#id_date_to').datepicker("option", $.datepicker.regional[ code_language ] );
164 }
165
166 set_language_code();
167
168
169 });
170
171 </script>
172
173{% endblock extra_js %}
174
175{% block footer %}
176{% endblock footer %}