Django csv example 1

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 %}