From b36b8d503a8f18181ae8eb098ae06883a0586ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Hamal=20Dvo=C5=99=C3=A1k?= <mordae@anilinux.org> Date: Tue, 17 Aug 2021 17:34:08 +0200 Subject: [PATCH] elections2021: Add a CSV export of banner orders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Hamal Dvořák <mordae@anilinux.org> --- .../migrations/0038_auto_20210817_1303.py | 264 ++++++++++++++++-- .../0039_elections2021mappage_subtitle.py | 10 +- ...me_place_of_birth_bannerorder_residency.py | 18 ++ elections2021/migrations/0041_token.py | 22 ++ elections2021/models.py | 87 +++--- .../elections2021/banner_order_form.html | 8 +- elections2021/views.py | 20 ++ majak/urls.py | 6 + 8 files changed, 366 insertions(+), 69 deletions(-) create mode 100644 elections2021/migrations/0040_rename_place_of_birth_bannerorder_residency.py create mode 100644 elections2021/migrations/0041_token.py create mode 100644 elections2021/views.py diff --git a/elections2021/migrations/0038_auto_20210817_1303.py b/elections2021/migrations/0038_auto_20210817_1303.py index 0a37bbd2..f56e2f7d 100644 --- a/elections2021/migrations/0038_auto_20210817_1303.py +++ b/elections2021/migrations/0038_auto_20210817_1303.py @@ -1,55 +1,261 @@ # Generated by Django 3.2.5 on 2021-08-17 11:03 -from django.db import migrations, models import django.db.models.deletion -import shared.models import wagtail.core.blocks import wagtail.core.fields import wagtail.images.blocks import wagtailmetadata.models +from django.db import migrations, models + +import shared.models class Migration(migrations.Migration): dependencies = [ - ('wagtailimages', '0023_add_choose_permissions'), - ('wagtailcore', '0062_comment_models_and_pagesubscription'), - ('elections2021', '0037_bannerorder_elections2021bannerlistpage'), + ("wagtailimages", "0023_add_choose_permissions"), + ("wagtailcore", "0062_comment_models_and_pagesubscription"), + ("elections2021", "0037_bannerorder_elections2021bannerlistpage"), ] operations = [ migrations.AlterModelOptions( - name='elections2021bannerlistpage', - options={'verbose_name': 'nabídka plachet'}, + name="elections2021bannerlistpage", + options={"verbose_name": "nabídka plachet"}, ), migrations.AlterField( - model_name='elections2021bannerlistpage', - name='banners', - field=wagtail.core.fields.StreamField([('banners', wagtail.core.blocks.StructBlock([('code', wagtail.core.blocks.CharBlock(label='kód banneru')), ('candidate1', wagtail.core.blocks.CharBlock(label='první kandidát', required=False)), ('candidate2', wagtail.core.blocks.CharBlock(label='druhý kandidát', required=False)), ('tagline', wagtail.core.blocks.CharBlock(label='slogan', required=False)), ('preview', wagtail.images.blocks.ImageChooserBlock(label='náhled'))]))], blank=True, verbose_name='objednávání plachet'), + model_name="elections2021bannerlistpage", + name="banners", + field=wagtail.core.fields.StreamField( + [ + ( + "banners", + wagtail.core.blocks.StructBlock( + [ + ( + "code", + wagtail.core.blocks.CharBlock(label="kód banneru"), + ), + ( + "candidate1", + wagtail.core.blocks.CharBlock( + label="první kandidát", required=False + ), + ), + ( + "candidate2", + wagtail.core.blocks.CharBlock( + label="druhý kandidát", required=False + ), + ), + ( + "tagline", + wagtail.core.blocks.CharBlock( + label="slogan", required=False + ), + ), + ( + "preview", + wagtail.images.blocks.ImageChooserBlock( + label="náhled" + ), + ), + ] + ), + ) + ], + blank=True, + verbose_name="objednávání plachet", + ), ), migrations.CreateModel( - name='Elections2021MapPage', + name="Elections2021MapPage", fields=[ - ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), - ('jihocesky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Jihočeský')), - ('jihomoravsky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Jihomoravsý')), - ('karlovarsky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Karlovarský')), - ('kralovehradecky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Královéhradecký')), - ('liberecky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Liberecký')), - ('moravskoslezsky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Moravskoslezský')), - ('olomoucky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Olomoucký')), - ('pardubicky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Pardubický')), - ('plzensky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Plzeňský')), - ('praha', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Praha')), - ('search_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Search image')), - ('stredocesky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Středočeský')), - ('ustecky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Ústecký')), - ('vysocina', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Vysočina')), - ('zlinsky', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Zlínský')), + ( + "page_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="wagtailcore.page", + ), + ), + ( + "jihocesky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Jihočeský", + ), + ), + ( + "jihomoravsky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Jihomoravsý", + ), + ), + ( + "karlovarsky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Karlovarský", + ), + ), + ( + "kralovehradecky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Královéhradecký", + ), + ), + ( + "liberecky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Liberecký", + ), + ), + ( + "moravskoslezsky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Moravskoslezský", + ), + ), + ( + "olomoucky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Olomoucký", + ), + ), + ( + "pardubicky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Pardubický", + ), + ), + ( + "plzensky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Plzeňský", + ), + ), + ( + "praha", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Praha", + ), + ), + ( + "search_image", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailimages.image", + verbose_name="Search image", + ), + ), + ( + "stredocesky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Středočeský", + ), + ), + ( + "ustecky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Ústecký", + ), + ), + ( + "vysocina", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Vysočina", + ), + ), + ( + "zlinsky", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + verbose_name="Zlínský", + ), + ), ], options={ - 'verbose_name': 'mapa krajů', + "verbose_name": "mapa krajů", }, - bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + bases=( + shared.models.SubpageMixin, + wagtailmetadata.models.WagtailImageMetadataMixin, + "wagtailcore.page", + models.Model, + ), ), ] diff --git a/elections2021/migrations/0039_elections2021mappage_subtitle.py b/elections2021/migrations/0039_elections2021mappage_subtitle.py index 827b845f..c839d30e 100644 --- a/elections2021/migrations/0039_elections2021mappage_subtitle.py +++ b/elections2021/migrations/0039_elections2021mappage_subtitle.py @@ -6,13 +6,15 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('elections2021', '0038_auto_20210817_1303'), + ("elections2021", "0038_auto_20210817_1303"), ] operations = [ migrations.AddField( - model_name='elections2021mappage', - name='subtitle', - field=models.CharField(blank=True, max_length=100, verbose_name='podtitulek'), + model_name="elections2021mappage", + name="subtitle", + field=models.CharField( + blank=True, max_length=100, verbose_name="podtitulek" + ), ), ] diff --git a/elections2021/migrations/0040_rename_place_of_birth_bannerorder_residency.py b/elections2021/migrations/0040_rename_place_of_birth_bannerorder_residency.py new file mode 100644 index 00000000..53644f90 --- /dev/null +++ b/elections2021/migrations/0040_rename_place_of_birth_bannerorder_residency.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.5 on 2021-08-17 15:04 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('elections2021', '0039_elections2021mappage_subtitle'), + ] + + operations = [ + migrations.RenameField( + model_name='bannerorder', + old_name='place_of_birth', + new_name='residency', + ), + ] diff --git a/elections2021/migrations/0041_token.py b/elections2021/migrations/0041_token.py new file mode 100644 index 00000000..c0a22302 --- /dev/null +++ b/elections2021/migrations/0041_token.py @@ -0,0 +1,22 @@ +# Generated by Django 3.2.5 on 2021-08-17 15:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('elections2021', '0040_rename_place_of_birth_bannerorder_residency'), + ] + + operations = [ + migrations.CreateModel( + name='Token', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('scope', models.CharField(max_length=127)), + ('bearer', models.CharField(max_length=40)), + ('comment', models.CharField(max_length=255)), + ], + ), + ] diff --git a/elections2021/models.py b/elections2021/models.py index 4687d549..a463a62d 100644 --- a/elections2021/models.py +++ b/elections2021/models.py @@ -2450,6 +2450,12 @@ class Elections2021CalendarPage(SubpageMixin, MetadataPageMixin, CalendarMixin, return self.calendar +class Token(models.Model): + scope = models.CharField(max_length=127) + bearer = models.CharField(max_length=40) + comment = models.CharField(max_length=255) + + class BannerBlock(blocks.StructBlock): code = blocks.CharBlock(label="kód banneru") candidate1 = blocks.CharBlock(label="první kandidát", required=False) @@ -2467,7 +2473,7 @@ class BannerOrder(models.Model): code = models.CharField(max_length=10) name = models.CharField(max_length=35) surname = models.CharField(max_length=70) - place_of_birth = models.CharField(max_length=70) + residency = models.CharField(max_length=70) date_of_birth = models.DateField() phone = models.CharField(max_length=20) email = models.EmailField(max_length=70) @@ -2480,7 +2486,7 @@ class BannerForm(forms.ModelForm): "code", "name", "surname", - "place_of_birth", + "residency", "date_of_birth", "phone", "email", @@ -2551,7 +2557,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): subtitle = models.CharField(max_length=100, blank=True, verbose_name="podtitulek") - praha = models.ForeignKey("wagtailcore.Page", + praha = models.ForeignKey( + "wagtailcore.Page", verbose_name="Praha", null=True, blank=True, @@ -2559,7 +2566,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - stredocesky = models.ForeignKey("wagtailcore.Page", + stredocesky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Středočeský", null=True, blank=True, @@ -2567,7 +2575,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - jihocesky = models.ForeignKey("wagtailcore.Page", + jihocesky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Jihočeský", null=True, blank=True, @@ -2575,7 +2584,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - plzensky = models.ForeignKey("wagtailcore.Page", + plzensky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Plzeňský", null=True, blank=True, @@ -2583,7 +2593,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - karlovarsky = models.ForeignKey("wagtailcore.Page", + karlovarsky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Karlovarský", null=True, blank=True, @@ -2591,7 +2602,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - ustecky = models.ForeignKey("wagtailcore.Page", + ustecky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Ústecký", null=True, blank=True, @@ -2599,7 +2611,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - liberecky = models.ForeignKey("wagtailcore.Page", + liberecky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Liberecký", null=True, blank=True, @@ -2607,7 +2620,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - kralovehradecky = models.ForeignKey("wagtailcore.Page", + kralovehradecky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Královéhradecký", null=True, blank=True, @@ -2615,7 +2629,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - moravskoslezsky = models.ForeignKey("wagtailcore.Page", + moravskoslezsky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Moravskoslezský", null=True, blank=True, @@ -2623,7 +2638,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - pardubicky = models.ForeignKey("wagtailcore.Page", + pardubicky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Pardubický", null=True, blank=True, @@ -2631,7 +2647,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - vysocina = models.ForeignKey("wagtailcore.Page", + vysocina = models.ForeignKey( + "wagtailcore.Page", verbose_name="Vysočina", null=True, blank=True, @@ -2639,7 +2656,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - jihomoravsky = models.ForeignKey("wagtailcore.Page", + jihomoravsky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Jihomoravsý", null=True, blank=True, @@ -2647,7 +2665,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - olomoucky = models.ForeignKey("wagtailcore.Page", + olomoucky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Olomoucký", null=True, blank=True, @@ -2655,7 +2674,8 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): related_name="+", ) - zlinsky = models.ForeignKey("wagtailcore.Page", + zlinsky = models.ForeignKey( + "wagtailcore.Page", verbose_name="Zlínský", null=True, blank=True, @@ -2667,22 +2687,25 @@ class Elections2021MapPage(SubpageMixin, MetadataPageMixin, Page): content_panels = Page.content_panels + [ FieldPanel("subtitle"), - MultiFieldPanel([ - PageChooserPanel("praha", "wagtailcore.Page"), - PageChooserPanel("stredocesky", "wagtailcore.Page"), - PageChooserPanel("jihocesky", "wagtailcore.Page"), - PageChooserPanel("plzensky", "wagtailcore.Page"), - PageChooserPanel("karlovarsky", "wagtailcore.Page"), - PageChooserPanel("ustecky", "wagtailcore.Page"), - PageChooserPanel("liberecky", "wagtailcore.Page"), - PageChooserPanel("kralovehradecky", "wagtailcore.Page"), - PageChooserPanel("moravskoslezsky", "wagtailcore.Page"), - PageChooserPanel("pardubicky", "wagtailcore.Page"), - PageChooserPanel("vysocina", "wagtailcore.Page"), - PageChooserPanel("jihomoravsky", "wagtailcore.Page"), - PageChooserPanel("olomoucky", "wagtailcore.Page"), - PageChooserPanel("zlinsky", "wagtailcore.Page"), - ], "Rozcestník krajů"), + MultiFieldPanel( + [ + PageChooserPanel("praha", "wagtailcore.Page"), + PageChooserPanel("stredocesky", "wagtailcore.Page"), + PageChooserPanel("jihocesky", "wagtailcore.Page"), + PageChooserPanel("plzensky", "wagtailcore.Page"), + PageChooserPanel("karlovarsky", "wagtailcore.Page"), + PageChooserPanel("ustecky", "wagtailcore.Page"), + PageChooserPanel("liberecky", "wagtailcore.Page"), + PageChooserPanel("kralovehradecky", "wagtailcore.Page"), + PageChooserPanel("moravskoslezsky", "wagtailcore.Page"), + PageChooserPanel("pardubicky", "wagtailcore.Page"), + PageChooserPanel("vysocina", "wagtailcore.Page"), + PageChooserPanel("jihomoravsky", "wagtailcore.Page"), + PageChooserPanel("olomoucky", "wagtailcore.Page"), + PageChooserPanel("zlinsky", "wagtailcore.Page"), + ], + "Rozcestník krajů", + ), ] promote_panels = [ diff --git a/elections2021/templates/elections2021/banner_order_form.html b/elections2021/templates/elections2021/banner_order_form.html index 7df2ded7..c9942e8d 100644 --- a/elections2021/templates/elections2021/banner_order_form.html +++ b/elections2021/templates/elections2021/banner_order_form.html @@ -45,12 +45,12 @@ {% endfor %} </div> - <div class="form-field col-span-2 form-field-required {% if request.banner_form.errors.place_of_birth %}form-field--error{% endif %}"> - <label class="form-field__label" for="place_of_birth">Místo narození</label> + <div class="form-field col-span-2 form-field-required {% if request.banner_form.errors.residency %}form-field--error{% endif %}"> + <label class="form-field__label" for="residency">Obec trvalého pobytu</label> <div class="form-field__wrapper form-field__wrapper--shadowed"> - <input type="text" class="text-input form-field__control text-black" id="place_of_birth" name="place_of_birth" value="{{request.banner_form.place_of_birth.value|default_if_none:""}}" placeholder="Sedlíšťka" /> + <input type="text" class="text-input form-field__control text-black" id="residency" name="residency" value="{{request.banner_form.residency.value|default_if_none:""}}" placeholder="Sedlíšťka" /> </div> - {% for error in request.banner_form.errors.place_of_birth %} + {% for error in request.banner_form.errors.residency %} <div class="form-field__error">{{error}}</div> {% endfor %} </div> diff --git a/elections2021/views.py b/elections2021/views.py new file mode 100644 index 00000000..7ef2e82b --- /dev/null +++ b/elections2021/views.py @@ -0,0 +1,20 @@ +import csv +from .models import BannerOrder, Token +from django.http import HttpResponse, HttpResponseForbidden + + +def banner_orders_csv(request): + response = HttpResponse(content_type='text/csv;charset=utf-8') + + tokens = Token.objects.filter(bearer=request.GET.get('token'), scope="banner-orders") + if not tokens: + return HttpResponseForbidden() + + w = csv.writer(response) + w.writerow(["ID", "Plachta", "Jméno", "Příjmení", "Bydliště", "Narozen", "Telefon", "Mail"]) + + for row in BannerOrder.objects.all(): + w.writerow([str(row.id), row.code, row.name, row.surname, row.residency, + str(row.date_of_birth), row.phone, row.email]) + + return response diff --git a/majak/urls.py b/majak/urls.py index 44cf8412..5f18ce5c 100644 --- a/majak/urls.py +++ b/majak/urls.py @@ -7,6 +7,7 @@ from wagtail.admin import urls as wagtailadmin_urls from wagtail.core import urls as wagtail_urls from wagtail.documents import urls as wagtaildocs_urls +from elections2021 import views as elections2021_views from search import views as search_views urlpatterns = [ @@ -14,6 +15,11 @@ urlpatterns = [ url(r"^admin/", include(wagtailadmin_urls)), url(r"^documents/", include(wagtaildocs_urls)), url(r"^search/$", search_views.search, name="search"), + url( + r"^export/elections2021/banner-orders.csv$", + elections2021_views.banner_orders_csv, + name="elections2021_banner_orders_csv", + ), url(r"^captcha/", include(captcha.urls)), ] + pirates_urlpatterns -- GitLab