Préparation de l'analyse de résultats
This commit is contained in:
parent
b1aee3ad07
commit
56358048f4
|
@ -0,0 +1,238 @@
|
||||||
|
"""Ajout des modèles de résultats pour les européennes 2024 + géométrie administrative
|
||||||
|
|
||||||
|
Revision ID: 42ff9c981be7
|
||||||
|
Revises:
|
||||||
|
Create Date: 2024-06-08 17:40:27.348858
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = '42ff9c981be7'
|
||||||
|
down_revision: Union[str, None] = None
|
||||||
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('bloc2024',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nom', sa.String(length=32), nullable=False),
|
||||||
|
sa.Column('couleur', sa.String(length=7), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('nom')
|
||||||
|
)
|
||||||
|
op.create_table('nuance2024',
|
||||||
|
sa.Column('code', sa.String(length=8), nullable=False),
|
||||||
|
sa.Column('nom', sa.String(length=32), nullable=False),
|
||||||
|
sa.Column('couleur', sa.String(length=7), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('code'),
|
||||||
|
sa.UniqueConstraint('nom')
|
||||||
|
)
|
||||||
|
op.create_table('region',
|
||||||
|
sa.Column('code_insee', sa.String(length=3), nullable=False),
|
||||||
|
sa.Column('libelle', sa.String(length=64), nullable=False),
|
||||||
|
sa.Column('geometry', sa.JSON(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('code_insee'),
|
||||||
|
sa.UniqueConstraint('libelle')
|
||||||
|
)
|
||||||
|
op.create_table('resultats2024_france',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('inscrits', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('votants', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('abstentions', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('exprimes', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('blancs', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nuls', sa.Integer(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('departement',
|
||||||
|
sa.Column('code_insee', sa.String(length=2), nullable=False),
|
||||||
|
sa.Column('libelle', sa.String(length=64), nullable=False),
|
||||||
|
sa.Column('region_code', sa.String(length=3), nullable=False),
|
||||||
|
sa.Column('geometry', sa.JSON(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['region_code'], ['region.code_insee'], ),
|
||||||
|
sa.PrimaryKeyConstraint('code_insee'),
|
||||||
|
sa.UniqueConstraint('libelle')
|
||||||
|
)
|
||||||
|
op.create_table('liste2024',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nom', sa.String(length=256), nullable=False),
|
||||||
|
sa.Column('nom_majuscules', sa.String(length=256), nullable=False),
|
||||||
|
sa.Column('numero', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nuance_id', sa.String(length=8), nullable=False),
|
||||||
|
sa.Column('bloc_id', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['bloc_id'], ['bloc2024.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['nuance_id'], ['nuance2024.code'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('nom'),
|
||||||
|
sa.UniqueConstraint('nom_majuscules'),
|
||||||
|
sa.UniqueConstraint('numero')
|
||||||
|
)
|
||||||
|
op.create_table('resultats2024_region',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('region_id', sa.String(length=3), nullable=False),
|
||||||
|
sa.Column('resultats_france_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('inscrits', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('votants', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('abstentions', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('exprimes', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('blancs', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nuls', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['region_id'], ['region.code_insee'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_france_id'], ['resultats2024_france.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('candidat2024',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('liste_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('ordre', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nom', sa.String(length=256), nullable=False),
|
||||||
|
sa.Column('prenom', sa.String(length=256), nullable=False),
|
||||||
|
sa.Column('sexe', sa.Enum('MASCULIN', 'FEMININ', name='genre'), nullable=False),
|
||||||
|
sa.Column('date_naissance', sa.Date(), nullable=False),
|
||||||
|
sa.Column('profession', sa.String(length=256), nullable=False),
|
||||||
|
sa.Column('code_personnalite', sa.Enum('DEFAUT', 'EURODEPUTE', 'DEPUTE', 'SENATEUR', 'MINISTRE', 'PRESIDENT_CONSEIL_REGIONAL', 'PRESIDENT_CONSEIL_DEPARTEMENTAL', 'MAIRE', name='personnalite'), nullable=False),
|
||||||
|
sa.Column('sortant', sa.Boolean(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['liste_id'], ['liste2024.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('circonscription',
|
||||||
|
sa.Column('id', sa.String(length=6), nullable=False),
|
||||||
|
sa.Column('departement_code', sa.String(length=2), nullable=False),
|
||||||
|
sa.Column('numero', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['departement_code'], ['departement.code_insee'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('commune',
|
||||||
|
sa.Column('code_insee', sa.String(length=5), nullable=False),
|
||||||
|
sa.Column('libelle', sa.String(length=64), nullable=False),
|
||||||
|
sa.Column('departement_code', sa.String(length=2), nullable=False),
|
||||||
|
sa.Column('geometry', sa.JSON(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['departement_code'], ['departement.code_insee'], ),
|
||||||
|
sa.PrimaryKeyConstraint('code_insee')
|
||||||
|
)
|
||||||
|
op.create_table('resultats2024_departement',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('dpt_id', sa.String(length=2), nullable=False),
|
||||||
|
sa.Column('resultats_region_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('inscrits', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('votants', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('abstentions', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('exprimes', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('blancs', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nuls', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['dpt_id'], ['departement.code_insee'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_region_id'], ['resultats2024_region.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('voix2024_france',
|
||||||
|
sa.Column('liste_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('resultats_france_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('voix', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['liste_id'], ['liste2024.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_france_id'], ['resultats2024_france.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('liste_id', 'resultats_france_id')
|
||||||
|
)
|
||||||
|
op.create_table('voix2024_region',
|
||||||
|
sa.Column('liste_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('resultats_region_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('voix', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['liste_id'], ['liste2024.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_region_id'], ['resultats2024_region.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('liste_id', 'resultats_region_id')
|
||||||
|
)
|
||||||
|
op.create_table('bureau_vote',
|
||||||
|
sa.Column('id', sa.String(length=16), nullable=False),
|
||||||
|
sa.Column('commune_code', sa.String(length=5), nullable=False),
|
||||||
|
sa.Column('code_bureau', sa.String(length=8), nullable=False),
|
||||||
|
sa.Column('circo_code', sa.String(length=6), nullable=False),
|
||||||
|
sa.Column('libelle', sa.String(length=256), nullable=False),
|
||||||
|
sa.Column('adresse', sa.String(length=256), nullable=True),
|
||||||
|
sa.Column('geometry', sa.JSON(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['circo_code'], ['circonscription.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['commune_code'], ['commune.code_insee'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('resultats2024_commune',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('commune_id', sa.String(length=5), nullable=False),
|
||||||
|
sa.Column('resultats_dpt_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('inscrits', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('votants', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('abstentions', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('exprimes', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('blancs', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nuls', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['commune_id'], ['commune.code_insee'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_dpt_id'], ['resultats2024_departement.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('voix2024_departement',
|
||||||
|
sa.Column('liste_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('resultats_departement_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('voix', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['liste_id'], ['liste2024.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_departement_id'], ['resultats2024_departement.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('liste_id', 'resultats_departement_id')
|
||||||
|
)
|
||||||
|
op.create_table('resultats2024_bureau_vote',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('bv_id', sa.String(length=16), nullable=False),
|
||||||
|
sa.Column('resultats_commune_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('inscrits', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('votants', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('abstentions', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('exprimes', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('blancs', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('nuls', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['bv_id'], ['bureau_vote.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_commune_id'], ['resultats2024_commune.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('voix2024_commune',
|
||||||
|
sa.Column('liste_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('resultats_commune_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('voix', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['liste_id'], ['liste2024.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_commune_id'], ['resultats2024_commune.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('liste_id', 'resultats_commune_id')
|
||||||
|
)
|
||||||
|
op.create_table('voix2024_bureau_vote',
|
||||||
|
sa.Column('liste_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('resultats_bureau_vote_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('voix', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['liste_id'], ['liste2024.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['resultats_bureau_vote_id'], ['resultats2024_bureau_vote.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('liste_id', 'resultats_bureau_vote_id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('voix2024_bureau_vote')
|
||||||
|
op.drop_table('voix2024_commune')
|
||||||
|
op.drop_table('resultats2024_bureau_vote')
|
||||||
|
op.drop_table('voix2024_departement')
|
||||||
|
op.drop_table('resultats2024_commune')
|
||||||
|
op.drop_table('bureau_vote')
|
||||||
|
op.drop_table('voix2024_region')
|
||||||
|
op.drop_table('voix2024_france')
|
||||||
|
op.drop_table('resultats2024_departement')
|
||||||
|
op.drop_table('commune')
|
||||||
|
op.drop_table('circonscription')
|
||||||
|
op.drop_table('candidat2024')
|
||||||
|
op.drop_table('resultats2024_region')
|
||||||
|
op.drop_table('liste2024')
|
||||||
|
op.drop_table('departement')
|
||||||
|
op.drop_table('resultats2024_france')
|
||||||
|
op.drop_table('region')
|
||||||
|
op.drop_table('nuance2024')
|
||||||
|
op.drop_table('bloc2024')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -1,76 +0,0 @@
|
||||||
"""Ajout des modèles de géométries administratives
|
|
||||||
|
|
||||||
Revision ID: 62495c819f2b
|
|
||||||
Revises: 9d99f3ea6b66
|
|
||||||
Create Date: 2024-06-08 16:13:15.457114
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '62495c819f2b'
|
|
||||||
down_revision: Union[str, None] = '9d99f3ea6b66'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.create_table('region',
|
|
||||||
sa.Column('code_insee', sa.String(length=3), nullable=False),
|
|
||||||
sa.Column('libelle', sa.String(length=64), nullable=False),
|
|
||||||
sa.Column('geometry', sa.JSON(), nullable=False),
|
|
||||||
sa.PrimaryKeyConstraint('code_insee'),
|
|
||||||
sa.UniqueConstraint('libelle')
|
|
||||||
)
|
|
||||||
op.create_table('departement',
|
|
||||||
sa.Column('code_insee', sa.String(length=2), nullable=False),
|
|
||||||
sa.Column('libelle', sa.String(length=64), nullable=False),
|
|
||||||
sa.Column('region_code', sa.String(length=3), nullable=False),
|
|
||||||
sa.Column('geometry', sa.JSON(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['region_code'], ['region.code_insee'], ),
|
|
||||||
sa.PrimaryKeyConstraint('code_insee'),
|
|
||||||
sa.UniqueConstraint('libelle')
|
|
||||||
)
|
|
||||||
op.create_table('circonscription',
|
|
||||||
sa.Column('id', sa.String(length=6), nullable=False),
|
|
||||||
sa.Column('departement_code', sa.String(length=2), nullable=False),
|
|
||||||
sa.Column('numero', sa.Integer(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['departement_code'], ['departement.code_insee'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('commune',
|
|
||||||
sa.Column('code_insee', sa.String(length=5), nullable=False),
|
|
||||||
sa.Column('libelle', sa.String(length=64), nullable=False),
|
|
||||||
sa.Column('departement_code', sa.String(length=2), nullable=False),
|
|
||||||
sa.Column('geometry', sa.JSON(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['departement_code'], ['departement.code_insee'], ),
|
|
||||||
sa.PrimaryKeyConstraint('code_insee')
|
|
||||||
)
|
|
||||||
op.create_table('bureau_vote',
|
|
||||||
sa.Column('id', sa.String(length=16), nullable=False),
|
|
||||||
sa.Column('commune_code', sa.String(length=5), nullable=False),
|
|
||||||
sa.Column('code_bureau', sa.String(length=8), nullable=False),
|
|
||||||
sa.Column('circo_code', sa.String(length=6), nullable=False),
|
|
||||||
sa.Column('libelle', sa.String(length=256), nullable=False),
|
|
||||||
sa.Column('adresse', sa.String(length=256), nullable=True),
|
|
||||||
sa.Column('geometry', sa.JSON(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['circo_code'], ['circonscription.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['commune_code'], ['commune.code_insee'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_table('bureau_vote')
|
|
||||||
op.drop_table('commune')
|
|
||||||
op.drop_table('circonscription')
|
|
||||||
op.drop_table('departement')
|
|
||||||
op.drop_table('region')
|
|
||||||
# ### end Alembic commands ###
|
|
|
@ -1,72 +0,0 @@
|
||||||
"""Ajout des modèles de candidat⋅es 2024
|
|
||||||
|
|
||||||
Revision ID: 9d99f3ea6b66
|
|
||||||
Revises:
|
|
||||||
Create Date: 2024-06-08 13:01:08.629780
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '9d99f3ea6b66'
|
|
||||||
down_revision: Union[str, None] = None
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.create_table('bloc2024',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('nom', sa.String(length=32), nullable=False),
|
|
||||||
sa.Column('couleur', sa.String(length=7), nullable=False),
|
|
||||||
sa.PrimaryKeyConstraint('id'),
|
|
||||||
sa.UniqueConstraint('nom')
|
|
||||||
)
|
|
||||||
op.create_table('nuance2024',
|
|
||||||
sa.Column('code', sa.String(length=8), nullable=False),
|
|
||||||
sa.Column('nom', sa.String(length=32), nullable=False),
|
|
||||||
sa.Column('couleur', sa.String(length=7), nullable=False),
|
|
||||||
sa.PrimaryKeyConstraint('code'),
|
|
||||||
sa.UniqueConstraint('nom')
|
|
||||||
)
|
|
||||||
op.create_table('liste2024',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('nom', sa.String(length=256), nullable=False),
|
|
||||||
sa.Column('numero', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('nuance_id', sa.String(length=8), nullable=False),
|
|
||||||
sa.Column('bloc_id', sa.Integer(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['bloc_id'], ['bloc2024.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['nuance_id'], ['nuance2024.code'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id'),
|
|
||||||
sa.UniqueConstraint('nom'),
|
|
||||||
sa.UniqueConstraint('numero')
|
|
||||||
)
|
|
||||||
op.create_table('candidat2024',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('liste_id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('ordre', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('nom', sa.String(length=256), nullable=False),
|
|
||||||
sa.Column('prenom', sa.String(length=256), nullable=False),
|
|
||||||
sa.Column('sexe', sa.Enum('MASCULIN', 'FEMININ', name='genre'), nullable=False),
|
|
||||||
sa.Column('date_naissance', sa.Date(), nullable=False),
|
|
||||||
sa.Column('profession', sa.String(length=256), nullable=False),
|
|
||||||
sa.Column('code_personnalite', sa.Enum('DEFAUT', 'EURODEPUTE', 'DEPUTE', 'SENATEUR', 'MINISTRE', 'PRESIDENT_CONSEIL_REGIONAL', 'PRESIDENT_CONSEIL_DEPARTEMENTAL', 'MAIRE', name='personnalite'), nullable=False),
|
|
||||||
sa.Column('sortant', sa.Boolean(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['liste_id'], ['liste2024.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_table('candidat2024')
|
|
||||||
op.drop_table('liste2024')
|
|
||||||
op.drop_table('nuance2024')
|
|
||||||
op.drop_table('bloc2024')
|
|
||||||
# ### end Alembic commands ###
|
|
7
main.py
7
main.py
|
@ -6,7 +6,7 @@ import os
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
|
|
||||||
from nupes.scripts import import_candidats_2024, import_geographie
|
from nupes.scripts import import_candidats_2024, import_geographie, import_resultats_web_2024
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
|
@ -16,7 +16,7 @@ def parse_args():
|
||||||
"régionales", "départementales", "municipales"], default="européennes")
|
"régionales", "départementales", "municipales"], default="européennes")
|
||||||
parser.add_argument('--year', '-y', type=int, help="Année de l'élection", default=2024)
|
parser.add_argument('--year', '-y', type=int, help="Année de l'élection", default=2024)
|
||||||
parser.add_argument('action', help="Action à réaliser",
|
parser.add_argument('action', help="Action à réaliser",
|
||||||
choices=["import_candidats", "import_geographie"])
|
choices=["import_candidats", "import_geographie", "import_resultats"])
|
||||||
parser.add_argument('--debug', '-d', action='store_true', help="Mode debug")
|
parser.add_argument('--debug', '-d', action='store_true', help="Mode debug")
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
@ -35,6 +35,9 @@ def main():
|
||||||
case "import_candidats":
|
case "import_candidats":
|
||||||
print(f"Import des candidats pour les élections {args.type} {args.year}")
|
print(f"Import des candidats pour les élections {args.type} {args.year}")
|
||||||
import_candidats_2024.run(engine)
|
import_candidats_2024.run(engine)
|
||||||
|
case "import_resultats":
|
||||||
|
print(f"Import des résultats pour les élections {args.type} {args.year}")
|
||||||
|
import_resultats_web_2024.run(engine)
|
||||||
case _:
|
case _:
|
||||||
print(f"Action {args.action} non reconnue")
|
print(f"Action {args.action} non reconnue")
|
||||||
|
|
||||||
|
|
|
@ -6,21 +6,41 @@ import requests
|
||||||
DATA_DIR = Path(__file__).parent / 'data'
|
DATA_DIR = Path(__file__).parent / 'data'
|
||||||
|
|
||||||
|
|
||||||
def get_file(url, filename, etag: str = None):
|
def get_file(url, filename, force_etag: str = ""):
|
||||||
if not DATA_DIR.is_dir():
|
if not DATA_DIR.is_dir():
|
||||||
DATA_DIR.mkdir()
|
DATA_DIR.mkdir(parents=True)
|
||||||
|
|
||||||
head_response = requests.head(url, allow_redirects=True)
|
file_dir = DATA_DIR / filename
|
||||||
headers = head_response.headers
|
if not file_dir.is_dir():
|
||||||
if not etag:
|
file_dir.mkdir(parents=True)
|
||||||
etag = headers.get('ETag').split('/')[-1].replace('"', '')
|
|
||||||
|
|
||||||
file = DATA_DIR / filename.format(etag=etag)
|
symlink_file = file_dir / 'latest'
|
||||||
if file.exists():
|
|
||||||
return file
|
etag = ""
|
||||||
|
if symlink_file.exists():
|
||||||
|
file = symlink_file.resolve()
|
||||||
|
etag = file.name
|
||||||
|
|
||||||
|
response = requests.get(url, headers={"If-None-Match": f'"{etag}'}, allow_redirects=True)
|
||||||
|
if response.status_code == 404:
|
||||||
|
print(url)
|
||||||
|
return None
|
||||||
|
response.raise_for_status()
|
||||||
|
if response.status_code != 304:
|
||||||
|
if force_etag:
|
||||||
|
etag = force_etag
|
||||||
|
else:
|
||||||
|
etag = response.headers.get('ETag').split('/')[-1].replace('"', '')
|
||||||
|
|
||||||
|
if symlink_file.exists():
|
||||||
|
symlink_file.resolve().unlink()
|
||||||
|
|
||||||
|
file = file_dir / etag
|
||||||
|
|
||||||
response = requests.get(url, allow_redirects=True)
|
|
||||||
with file.open('wb') as f:
|
with file.open('wb') as f:
|
||||||
f.write(response.content)
|
f.write(response.content)
|
||||||
|
|
||||||
return file
|
symlink_file.unlink(missing_ok=True)
|
||||||
|
symlink_file.symlink_to(file)
|
||||||
|
|
||||||
|
return symlink_file
|
||||||
|
|
|
@ -5,7 +5,7 @@ from typing import List
|
||||||
from sqlalchemy import Boolean, Date, Enum, ForeignKey, Integer, String
|
from sqlalchemy import Boolean, Date, Enum, ForeignKey, Integer, String
|
||||||
from sqlalchemy.orm import mapped_column, Mapped, relationship
|
from sqlalchemy.orm import mapped_column, Mapped, relationship
|
||||||
|
|
||||||
from nupes.models import Base
|
from nupes.models import Base, Region, Departement, Commune
|
||||||
|
|
||||||
|
|
||||||
class Bloc(Base):
|
class Bloc(Base):
|
||||||
|
@ -33,12 +33,22 @@ class Liste(Base):
|
||||||
|
|
||||||
id: Mapped[int] = mapped_column(primary_key=True)
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
nom: Mapped[str] = mapped_column(String(256), unique=True)
|
nom: Mapped[str] = mapped_column(String(256), unique=True)
|
||||||
|
nom_majuscules: Mapped[str] = mapped_column(String(256), unique=True, nullable=True)
|
||||||
numero: Mapped[int] = mapped_column(Integer(), unique=True)
|
numero: Mapped[int] = mapped_column(Integer(), unique=True)
|
||||||
nuance_id: Mapped[str] = mapped_column(ForeignKey("nuance2024.code"))
|
nuance_id: Mapped[str] = mapped_column(ForeignKey("nuance2024.code"))
|
||||||
bloc_id: Mapped[int] = mapped_column(ForeignKey("bloc2024.id"))
|
bloc_id: Mapped[int] = mapped_column(ForeignKey("bloc2024.id"))
|
||||||
|
|
||||||
nuance: Mapped[Nuance] = relationship(Nuance, back_populates="listes")
|
nuance: Mapped[Nuance] = relationship(Nuance, back_populates="listes")
|
||||||
bloc: Mapped[Bloc] = relationship(Bloc, back_populates="listes")
|
bloc: Mapped[Bloc] = relationship(Bloc, back_populates="listes")
|
||||||
|
candidats: Mapped[List["Candidat"]] = relationship("Candidat", back_populates="liste")
|
||||||
|
|
||||||
|
resultats_nationaux: Mapped[List["VoixListeFrance"]] = relationship("VoixListeFrance", back_populates="liste")
|
||||||
|
resultats_par_region: Mapped[List["VoixListeRegion"]] = relationship("VoixListeRegion", back_populates="liste")
|
||||||
|
resultats_par_departement: Mapped[List["VoixListeDepartement"]] = relationship("VoixListeDepartement",
|
||||||
|
back_populates="liste")
|
||||||
|
resultats_par_commune: Mapped[List["VoixListeCommune"]] = relationship("VoixListeCommune", back_populates="liste")
|
||||||
|
resultats_par_bureau_vote: Mapped[List["VoixListeBureauVote"]] = relationship("VoixListeBureauVote",
|
||||||
|
back_populates="liste")
|
||||||
|
|
||||||
|
|
||||||
class Candidat(Base):
|
class Candidat(Base):
|
||||||
|
@ -68,3 +78,157 @@ class Candidat(Base):
|
||||||
profession: Mapped[str] = mapped_column(String(256))
|
profession: Mapped[str] = mapped_column(String(256))
|
||||||
code_personnalite: Mapped[str] = mapped_column(Enum(Personnalite))
|
code_personnalite: Mapped[str] = mapped_column(Enum(Personnalite))
|
||||||
sortant: Mapped[bool] = mapped_column(Boolean())
|
sortant: Mapped[bool] = mapped_column(Boolean())
|
||||||
|
|
||||||
|
liste: Mapped[Liste] = relationship(Liste, back_populates="candidats")
|
||||||
|
|
||||||
|
|
||||||
|
class ResultatsFrance(Base):
|
||||||
|
__tablename__ = "resultats2024_france"
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
inscrits: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
votants: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
abstentions: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
exprimes: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
blancs: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
nuls: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
resultats_regions: Mapped[List["ResultatsRegion"]] = relationship("ResultatsRegion",
|
||||||
|
back_populates="resultats_france")
|
||||||
|
voix_listes: Mapped[List["VoixListeFrance"]] = relationship("VoixListeFrance", back_populates="resultats_france")
|
||||||
|
|
||||||
|
|
||||||
|
class ResultatsRegion(Base):
|
||||||
|
__tablename__ = "resultats2024_region"
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
region_id: Mapped[str] = mapped_column(ForeignKey("region.code_insee"))
|
||||||
|
resultats_france_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_france.id"))
|
||||||
|
inscrits: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
votants: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
abstentions: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
exprimes: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
blancs: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
nuls: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
region = relationship(Region, back_populates="resultats2024")
|
||||||
|
resultats_france = relationship(ResultatsFrance, back_populates="resultats_regions")
|
||||||
|
resultats_departements: Mapped[List["ResultatsDepartement"]] = relationship("ResultatsDepartement",
|
||||||
|
back_populates="resultats_region")
|
||||||
|
voix_listes: Mapped[List["VoixListeRegion"]] = relationship("VoixListeRegion", back_populates="resultats_region")
|
||||||
|
|
||||||
|
|
||||||
|
class ResultatsDepartement(Base):
|
||||||
|
__tablename__ = "resultats2024_departement"
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
dpt_id: Mapped[str] = mapped_column(ForeignKey("departement.code_insee"))
|
||||||
|
resultats_region_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_region.id"))
|
||||||
|
inscrits: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
votants: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
abstentions: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
exprimes: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
blancs: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
nuls: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
departement = relationship(Departement, back_populates="resultats2024")
|
||||||
|
resultats_region = relationship(ResultatsRegion, back_populates="resultats_departements")
|
||||||
|
resultats_communes: Mapped[List["ResultatsCommune"]] = relationship("ResultatsCommune",
|
||||||
|
back_populates="resultats_departement")
|
||||||
|
voix_listes: Mapped[List["VoixListeDepartement"]] = relationship("VoixListeDepartement",
|
||||||
|
back_populates="resultats_departement")
|
||||||
|
|
||||||
|
|
||||||
|
class ResultatsCommune(Base):
|
||||||
|
__tablename__ = "resultats2024_commune"
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
commune_id: Mapped[str] = mapped_column(ForeignKey("commune.code_insee"))
|
||||||
|
resultats_dpt_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_departement.id"))
|
||||||
|
inscrits: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
votants: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
abstentions: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
exprimes: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
blancs: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
nuls: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
commune = relationship(Commune, back_populates="resultats2024")
|
||||||
|
resultats_departement = relationship(ResultatsDepartement, back_populates="resultats_communes")
|
||||||
|
resultats_bureaux_vote: Mapped[List["ResultatsBureauVote"]] = relationship("ResultatsBureauVote",
|
||||||
|
back_populates="resultats_commune")
|
||||||
|
voix_listes: Mapped[List["VoixListeCommune"]] = relationship("VoixListeCommune", back_populates="resultats_commune")
|
||||||
|
|
||||||
|
|
||||||
|
class ResultatsBureauVote(Base):
|
||||||
|
__tablename__ = "resultats2024_bureau_vote"
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
bv_id: Mapped[str] = mapped_column(ForeignKey("bureau_vote.id"))
|
||||||
|
resultats_commune_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_commune.id"))
|
||||||
|
inscrits: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
votants: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
abstentions: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
exprimes: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
blancs: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
nuls: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
bureau_vote = relationship("BureauVote", back_populates="resultats2024")
|
||||||
|
resultats_commune = relationship(ResultatsCommune, back_populates="resultats_bureaux_vote")
|
||||||
|
voix_listes: Mapped[List["VoixListeBureauVote"]] = relationship("VoixListeBureauVote",
|
||||||
|
back_populates="resultats_bureau_vote")
|
||||||
|
|
||||||
|
|
||||||
|
class VoixListeFrance(Base):
|
||||||
|
__tablename__ = "voix2024_france"
|
||||||
|
|
||||||
|
liste_id: Mapped[int] = mapped_column(ForeignKey("liste2024.id"), primary_key=True)
|
||||||
|
resultats_france_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_france.id"), primary_key=True)
|
||||||
|
voix: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
liste: Mapped[Liste] = relationship(Liste, back_populates="resultats_nationaux")
|
||||||
|
resultats_france: Mapped[ResultatsFrance] = relationship(ResultatsFrance, back_populates="voix_listes")
|
||||||
|
|
||||||
|
|
||||||
|
class VoixListeRegion(Base):
|
||||||
|
__tablename__ = "voix2024_region"
|
||||||
|
|
||||||
|
liste_id: Mapped[int] = mapped_column(ForeignKey("liste2024.id"), primary_key=True)
|
||||||
|
resultats_region_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_region.id"), primary_key=True)
|
||||||
|
voix: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
liste: Mapped[Liste] = relationship(Liste, back_populates="resultats_par_region")
|
||||||
|
resultats_region: Mapped[ResultatsRegion] = relationship(ResultatsRegion, back_populates="voix_listes")
|
||||||
|
|
||||||
|
|
||||||
|
class VoixListeDepartement(Base):
|
||||||
|
__tablename__ = "voix2024_departement"
|
||||||
|
|
||||||
|
liste_id: Mapped[int] = mapped_column(ForeignKey("liste2024.id"), primary_key=True)
|
||||||
|
resultats_departement_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_departement.id"), primary_key=True)
|
||||||
|
voix: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
liste: Mapped[Liste] = relationship(Liste, back_populates="resultats_par_departement")
|
||||||
|
resultats_departement: Mapped[ResultatsDepartement] = relationship(ResultatsDepartement,
|
||||||
|
back_populates="voix_listes")
|
||||||
|
|
||||||
|
|
||||||
|
class VoixListeCommune(Base):
|
||||||
|
__tablename__ = "voix2024_commune"
|
||||||
|
|
||||||
|
liste_id: Mapped[int] = mapped_column(ForeignKey("liste2024.id"), primary_key=True)
|
||||||
|
resultats_commune_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_commune.id"), primary_key=True)
|
||||||
|
voix: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
liste: Mapped[Liste] = relationship(Liste, back_populates="resultats_par_commune")
|
||||||
|
resultats_commune: Mapped[ResultatsCommune] = relationship(ResultatsCommune, back_populates="voix_listes")
|
||||||
|
|
||||||
|
|
||||||
|
class VoixListeBureauVote(Base):
|
||||||
|
__tablename__ = "voix2024_bureau_vote"
|
||||||
|
|
||||||
|
liste_id: Mapped[int] = mapped_column(ForeignKey("liste2024.id"), primary_key=True)
|
||||||
|
resultats_bureau_vote_id: Mapped[int] = mapped_column(ForeignKey("resultats2024_bureau_vote.id"), primary_key=True)
|
||||||
|
voix: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|
||||||
|
liste: Mapped[Liste] = relationship(Liste, back_populates="resultats_par_bureau_vote")
|
||||||
|
resultats_bureau_vote: Mapped[ResultatsBureauVote] = relationship(ResultatsBureauVote, back_populates="voix_listes")
|
||||||
|
|
|
@ -15,6 +15,8 @@ class Region(Base):
|
||||||
|
|
||||||
departements: Mapped[List["Departement"]] = relationship("Departement", back_populates="region")
|
departements: Mapped[List["Departement"]] = relationship("Departement", back_populates="region")
|
||||||
|
|
||||||
|
resultats2024 = relationship("ResultatsRegion", back_populates="region")
|
||||||
|
|
||||||
|
|
||||||
class Departement(Base):
|
class Departement(Base):
|
||||||
__tablename__ = "departement"
|
__tablename__ = "departement"
|
||||||
|
@ -27,6 +29,8 @@ class Departement(Base):
|
||||||
region: Mapped[Region] = relationship(Region, back_populates="departements")
|
region: Mapped[Region] = relationship(Region, back_populates="departements")
|
||||||
communes: Mapped[List["Commune"]] = relationship("Commune", back_populates="departement")
|
communes: Mapped[List["Commune"]] = relationship("Commune", back_populates="departement")
|
||||||
|
|
||||||
|
resultats2024 = relationship("ResultatsDepartement", back_populates="departement")
|
||||||
|
|
||||||
|
|
||||||
class Commune(Base):
|
class Commune(Base):
|
||||||
__tablename__ = "commune"
|
__tablename__ = "commune"
|
||||||
|
@ -39,6 +43,8 @@ class Commune(Base):
|
||||||
departement: Mapped[Departement] = relationship(Departement, back_populates="communes")
|
departement: Mapped[Departement] = relationship(Departement, back_populates="communes")
|
||||||
bureaux_vote: Mapped[List["BureauVote"]] = relationship("BureauVote", back_populates="commune")
|
bureaux_vote: Mapped[List["BureauVote"]] = relationship("BureauVote", back_populates="commune")
|
||||||
|
|
||||||
|
resultats2024 = relationship("ResultatsCommune", back_populates="commune")
|
||||||
|
|
||||||
|
|
||||||
class Circonscription(Base):
|
class Circonscription(Base):
|
||||||
__tablename__ = "circonscription"
|
__tablename__ = "circonscription"
|
||||||
|
@ -64,3 +70,5 @@ class BureauVote(Base):
|
||||||
|
|
||||||
commune: Mapped[Commune] = relationship(Commune, back_populates="bureaux_vote")
|
commune: Mapped[Commune] = relationship(Commune, back_populates="bureaux_vote")
|
||||||
circonscription: Mapped[Circonscription] = relationship(Circonscription, back_populates="bureaux_vote")
|
circonscription: Mapped[Circonscription] = relationship(Circonscription, back_populates="bureaux_vote")
|
||||||
|
|
||||||
|
resultats2024 = relationship("ResultatsBureauVote", back_populates="bureau_vote")
|
||||||
|
|
|
@ -118,14 +118,17 @@ def importer_listes(engine: Engine) -> None:
|
||||||
liste.nuance_id = liste_dict["nuance_id"]
|
liste.nuance_id = liste_dict["nuance_id"]
|
||||||
liste.bloc_id = liste_dict["bloc_id"]
|
liste.bloc_id = liste_dict["bloc_id"]
|
||||||
else:
|
else:
|
||||||
session.add(Liste(**liste_dict))
|
liste = Liste(numero=liste_dict['numero'], nom=liste_dict['nom'],
|
||||||
|
nom_majuscules=liste_dict['nom'].upper(), nuance_id=liste_dict['nuance_id'],
|
||||||
|
bloc_id=liste_dict['bloc_id'])
|
||||||
|
session.add(liste)
|
||||||
|
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
def importer_candidats(engine: Engine) -> None:
|
def importer_candidats(engine: Engine) -> None:
|
||||||
DATASET_URL = "https://www.data.gouv.fr/fr/datasets/r/483cd4bd-1b0e-4b52-a923-aadadf9c8f62"
|
DATASET_URL = "https://www.data.gouv.fr/fr/datasets/r/483cd4bd-1b0e-4b52-a923-aadadf9c8f62"
|
||||||
file = get_file(DATASET_URL, "candidats_2024-{etag}.csv")
|
file = get_file(DATASET_URL, "candidats_2024.csv")
|
||||||
|
|
||||||
with file.open('r') as f:
|
with file.open('r') as f:
|
||||||
with Session(engine) as session:
|
with Session(engine) as session:
|
||||||
|
@ -134,6 +137,7 @@ def importer_candidats(engine: Engine) -> None:
|
||||||
line: dict[str, str]
|
line: dict[str, str]
|
||||||
numero_panneau = line.get("Numéro de panneau")
|
numero_panneau = line.get("Numéro de panneau")
|
||||||
liste = session.execute(select(Liste).filter_by(numero=numero_panneau)).scalar_one()
|
liste = session.execute(select(Liste).filter_by(numero=numero_panneau)).scalar_one()
|
||||||
|
liste.nom_majuscules = line['Libellé de la liste']
|
||||||
|
|
||||||
if candidat := session.execute(select(Candidat).filter_by(liste_id=liste.id, ordre=line['Ordre'])) \
|
if candidat := session.execute(select(Candidat).filter_by(liste_id=liste.id, ordre=line['Ordre'])) \
|
||||||
.scalar_one_or_none():
|
.scalar_one_or_none():
|
||||||
|
|
|
@ -15,7 +15,7 @@ def importer_regions(engine: Engine) -> None:
|
||||||
"/georef-france-region?select=data_processed").json()['data_processed']
|
"/georef-france-region?select=data_processed").json()['data_processed']
|
||||||
file = get_file("https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets"
|
file = get_file("https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets"
|
||||||
"/georef-france-region/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
|
"/georef-france-region/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
|
||||||
"georef-france-region-{etag}.geojson", etag)
|
"georef-france-region.geojson", etag)
|
||||||
|
|
||||||
with file.open('r') as f:
|
with file.open('r') as f:
|
||||||
features = json.load(f)['features']
|
features = json.load(f)['features']
|
||||||
|
@ -42,7 +42,7 @@ def importer_departements(engine: Engine) -> None:
|
||||||
"/georef-france-departement?select=data_processed").json()['data_processed']
|
"/georef-france-departement?select=data_processed").json()['data_processed']
|
||||||
file = get_file("https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets"
|
file = get_file("https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets"
|
||||||
"/georef-france-departement/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
|
"/georef-france-departement/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
|
||||||
"georef-france-departement-{etag}.geojson", etag)
|
"georef-france-departement.geojson", etag)
|
||||||
|
|
||||||
|
|
||||||
with file.open('r') as f:
|
with file.open('r') as f:
|
||||||
|
@ -72,7 +72,7 @@ def importer_communes(engine: Engine) -> None:
|
||||||
"/georef-france-commune?select=data_processed").json()['data_processed']
|
"/georef-france-commune?select=data_processed").json()['data_processed']
|
||||||
file = get_file("https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets"
|
file = get_file("https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets"
|
||||||
"/georef-france-commune/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
|
"/georef-france-commune/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
|
||||||
"georef-france-commune-{etag}.geojson", etag)
|
"georef-france-commune.geojson", etag)
|
||||||
|
|
||||||
with file.open('r') as f:
|
with file.open('r') as f:
|
||||||
features = json.load(f)['features']
|
features = json.load(f)['features']
|
||||||
|
@ -101,7 +101,7 @@ def importer_bureaux_vote(engine: Engine) -> None:
|
||||||
"/elections-france-bureau-vote-2022?select=data_processed").json()['data_processed']
|
"/elections-france-bureau-vote-2022?select=data_processed").json()['data_processed']
|
||||||
file = get_file("https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets"
|
file = get_file("https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets"
|
||||||
"/elections-france-bureau-vote-2022/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
|
"/elections-france-bureau-vote-2022/exports/geojson?lang=fr&timezone=Europe%2FBerlin",
|
||||||
"elections-france-bureau-vote-2022-{etag}.geojson", etag)
|
"elections-france-bureau-vote-2022.geojson", etag)
|
||||||
|
|
||||||
with file.open('r') as f:
|
with file.open('r') as f:
|
||||||
features = json.load(f)['features']
|
features = json.load(f)['features']
|
||||||
|
@ -170,8 +170,8 @@ def importer_contours_bureaux_vote(engine: Engine) -> None:
|
||||||
|
|
||||||
|
|
||||||
def run(engine: Engine) -> None:
|
def run(engine: Engine) -> None:
|
||||||
# importer_regions(engine)
|
importer_regions(engine)
|
||||||
# importer_departements(engine)
|
importer_departements(engine)
|
||||||
# importer_communes(engine)
|
importer_communes(engine)
|
||||||
importer_bureaux_vote(engine)
|
importer_bureaux_vote(engine)
|
||||||
importer_contours_bureaux_vote(engine)
|
importer_contours_bureaux_vote(engine)
|
||||||
|
|
|
@ -0,0 +1,297 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from sqlalchemy import Engine, select
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from nupes.data import get_file
|
||||||
|
from nupes.models.europeennes2024 import ResultatsFrance, ResultatsRegion, ResultatsDepartement, ResultatsCommune, \
|
||||||
|
VoixListeFrance, VoixListeRegion, VoixListeDepartement, VoixListeCommune, Liste
|
||||||
|
from nupes.models.geographie import Region, Departement, Commune
|
||||||
|
|
||||||
|
BASE_URL = "https://www.resultats-elections.interieur.gouv.fr/europeennes2024/ensemble_geographique"
|
||||||
|
|
||||||
|
|
||||||
|
def importer_resultats_france(engine: Engine) -> None:
|
||||||
|
file = get_file(f"{BASE_URL}/index.html", "resultats2024/resultats.html")
|
||||||
|
|
||||||
|
with file.open() as f:
|
||||||
|
resultats = analyser_resultats(f)
|
||||||
|
|
||||||
|
if not resultats:
|
||||||
|
return
|
||||||
|
|
||||||
|
with Session(engine) as session:
|
||||||
|
if resultats_france := session.execute(select(ResultatsFrance)).scalar_one_or_none():
|
||||||
|
resultats_france.inscrits = resultats["inscrits"]
|
||||||
|
resultats_france.abstentions = resultats["abstentions"]
|
||||||
|
resultats_france.votants = resultats["votants"]
|
||||||
|
resultats_france.blancs = resultats["blancs"]
|
||||||
|
resultats_france.nuls = resultats["nuls"]
|
||||||
|
resultats_france.exprimes = resultats["exprimes"]
|
||||||
|
else:
|
||||||
|
resultats_france = ResultatsFrance(
|
||||||
|
inscrits=resultats["inscrits"],
|
||||||
|
abstentions=resultats["abstentions"],
|
||||||
|
votants=resultats["votants"],
|
||||||
|
blancs=resultats["blancs"],
|
||||||
|
nuls=resultats["nuls"],
|
||||||
|
exprimes=resultats["exprimes"],
|
||||||
|
)
|
||||||
|
session.add(resultats_france)
|
||||||
|
|
||||||
|
for voix_liste in resultats["resultats_par_liste"]:
|
||||||
|
if voix_liste_france := session.execute(
|
||||||
|
select(VoixListeFrance).join(Liste).filter_by(nom_majuscules=voix_liste["nom"].upper())
|
||||||
|
).scalar_one_or_none():
|
||||||
|
voix_liste_france.voix = voix_liste["voix"]
|
||||||
|
else:
|
||||||
|
liste = session.execute(select(Liste).filter_by(nom_majuscules=voix_liste["nom"].upper())).scalar_one()
|
||||||
|
voix_liste_france = VoixListeFrance(liste_id=liste.id, voix=voix_liste["voix"])
|
||||||
|
session.add(voix_liste_france)
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
def importer_resultats_regions(engine: Engine) -> None:
|
||||||
|
with Session(engine) as session:
|
||||||
|
for region in tqdm(session.execute(select(Region)).scalars().all(), desc="Régions"):
|
||||||
|
reg_code = region.code_insee
|
||||||
|
if reg_code == "984" or reg_code == "989":
|
||||||
|
# TAAF + Île de Clipperton, pas d'élection
|
||||||
|
continue
|
||||||
|
elif reg_code == "977" or reg_code == "978":
|
||||||
|
# Saint-Barthélemy et Saint-Martin, pas mis dans une région mais dans un unique département
|
||||||
|
continue
|
||||||
|
|
||||||
|
file = get_file(f"{BASE_URL}/{reg_code}/index.html",
|
||||||
|
f"resultats2024/region_{reg_code}/resultats.html")
|
||||||
|
|
||||||
|
with file.open() as f:
|
||||||
|
resultats = analyser_resultats(f)
|
||||||
|
|
||||||
|
if not resultats:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if resultats_region := session.execute(select(ResultatsRegion).filter_by(region_id=reg_code)) \
|
||||||
|
.scalar_one_or_none():
|
||||||
|
resultats_region.inscrits = resultats["inscrits"]
|
||||||
|
resultats_region.abstentions = resultats["abstentions"]
|
||||||
|
resultats_region.votants = resultats["votants"]
|
||||||
|
resultats_region.blancs = resultats["blancs"]
|
||||||
|
resultats_region.nuls = resultats["nuls"]
|
||||||
|
resultats_region.exprimes = resultats["exprimes"]
|
||||||
|
else:
|
||||||
|
resultats_region = ResultatsRegion(
|
||||||
|
region_id=reg_code,
|
||||||
|
inscrits=resultats["inscrits"],
|
||||||
|
abstentions=resultats["abstentions"],
|
||||||
|
votants=resultats["votants"],
|
||||||
|
blancs=resultats["blancs"],
|
||||||
|
nuls=resultats["nuls"],
|
||||||
|
exprimes=resultats["exprimes"],
|
||||||
|
)
|
||||||
|
session.add(resultats_region)
|
||||||
|
|
||||||
|
for voix_liste in resultats["resultats_par_liste"]:
|
||||||
|
if voix_liste_region := session.execute(
|
||||||
|
select(VoixListeRegion).join(Liste).filter_by(nom_majuscules=voix_liste["nom"].upper())
|
||||||
|
).scalar_one_or_none():
|
||||||
|
voix_liste_region.voix = voix_liste["voix"]
|
||||||
|
else:
|
||||||
|
liste = session.execute(select(Liste).filter_by(nom_majuscules=voix_liste["nom"].upper())) \
|
||||||
|
.scalar_one()
|
||||||
|
voix_liste_region = VoixListeRegion(liste_id=liste.id, voix=voix_liste["voix"])
|
||||||
|
session.add(voix_liste_region)
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def importer_resultats_departements(engine: Engine) -> None:
|
||||||
|
with Session(engine) as session:
|
||||||
|
for dpt in tqdm(session.execute(select(Departement)).scalars().all(), desc="Départements"):
|
||||||
|
reg_code = dpt.region_code
|
||||||
|
reg_path = f"{reg_code}/"
|
||||||
|
dpt_code = dpt.code_insee
|
||||||
|
if dpt_code == "984" or dpt_code == "989":
|
||||||
|
# TAAF + Île de Clipperton, pas d'élection
|
||||||
|
continue
|
||||||
|
elif dpt_code == "977" or dpt_code == "978":
|
||||||
|
# Pour une raison obscure, Saint-Barthélemy et Saint-Martin sont dans le département ZX
|
||||||
|
reg_path = ""
|
||||||
|
dpt_code = "ZX"
|
||||||
|
if dpt_code in ["975", "977", "978", "986", "987", "988"]:
|
||||||
|
# Pour ces collectivités d'outre-mer, qui ne sont pas dans des régions,
|
||||||
|
# on ne les regroupe pas dans des régions
|
||||||
|
reg_path = ""
|
||||||
|
|
||||||
|
file = get_file(f"{BASE_URL}/{reg_path}{dpt_code}/index.html",
|
||||||
|
f"resultats2024/region_{reg_code}/dpt_{dpt_code}/resultats.html")
|
||||||
|
|
||||||
|
with file.open() as f:
|
||||||
|
resultats = analyser_resultats(f)
|
||||||
|
|
||||||
|
if not resultats:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if resultats_departement := session.execute(
|
||||||
|
select(ResultatsDepartement).filter_by(dpt_id=dpt_code)).scalar_one_or_none():
|
||||||
|
resultats_departement.inscrits = resultats["inscrits"]
|
||||||
|
resultats_departement.abstentions = resultats["abstentions"]
|
||||||
|
resultats_departement.votants = resultats["votants"]
|
||||||
|
resultats_departement.blancs = resultats["blancs"]
|
||||||
|
resultats_departement.nuls = resultats["nuls"]
|
||||||
|
resultats_departement.exprimes = resultats["exprimes"]
|
||||||
|
else:
|
||||||
|
resultats_departement = ResultatsDepartement(
|
||||||
|
dpt_id=dpt_code,
|
||||||
|
inscrits=resultats["inscrits"],
|
||||||
|
abstentions=resultats["abstentions"],
|
||||||
|
votants=resultats["votants"],
|
||||||
|
blancs=resultats["blancs"],
|
||||||
|
nuls=resultats["nuls"],
|
||||||
|
exprimes=resultats["exprimes"],
|
||||||
|
)
|
||||||
|
session.add(resultats_departement)
|
||||||
|
|
||||||
|
for voix_liste in resultats["resultats_par_liste"]:
|
||||||
|
if voix_liste_departement := session.execute(
|
||||||
|
select(VoixListeDepartement).join(Liste).filter_by(nom_majuscules=voix_liste["nom"].upper())
|
||||||
|
).scalar_one_or_none():
|
||||||
|
voix_liste_departement.voix = voix_liste["voix"]
|
||||||
|
else:
|
||||||
|
liste = session.execute(select(Liste).filter_by(nom_majuscules=voix_liste["nom"].upper())) \
|
||||||
|
.scalar_one()
|
||||||
|
voix_liste_departement = VoixListeDepartement(liste_id=liste.id, voix=voix_liste["voix"])
|
||||||
|
session.add(voix_liste_departement)
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def importer_resultats_communes(engine: Engine) -> None:
|
||||||
|
with Session(engine) as session:
|
||||||
|
for commune in tqdm(session.execute(select(Commune)).scalars().all(), desc="Communes"):
|
||||||
|
reg_code = commune.departement.region_code
|
||||||
|
reg_path = f"{reg_code}/"
|
||||||
|
dpt_code = commune.departement_code
|
||||||
|
com_code = commune.code_insee
|
||||||
|
if dpt_code == "984" or dpt_code == "989":
|
||||||
|
# TAAF + Île de Clipperton, pas d'élection
|
||||||
|
continue
|
||||||
|
elif dpt_code == "977" or dpt_code == "978":
|
||||||
|
# Pour une raison obscure, Saint-Barthélemy et Saint-Martin sont dans le département ZX
|
||||||
|
reg_path = ""
|
||||||
|
dpt_code = "ZX"
|
||||||
|
com_code = f"ZX{com_code[2:]}"
|
||||||
|
if dpt_code in ["975", "977", "978", "986", "987", "988"]:
|
||||||
|
# Pour ces collectivités d'outre-mer, qui ne sont pas dans des régions,
|
||||||
|
# on ne les regroupe pas dans des régions
|
||||||
|
reg_path = ""
|
||||||
|
if com_code in ["16355", "25282", "55050", "55189", "69152"]:
|
||||||
|
# Aucun⋅e habitant⋅e donc pas de bureau de vote
|
||||||
|
# Ou alors la commune a récemment fusionné
|
||||||
|
continue
|
||||||
|
|
||||||
|
file = get_file(f"{BASE_URL}/{reg_path}{dpt_code}/{com_code}/index.html",
|
||||||
|
f"resultats2024/region_{reg_code}/dpt_{dpt_code}"
|
||||||
|
f"/commune_{com_code}/resultats.html")
|
||||||
|
if not file:
|
||||||
|
continue
|
||||||
|
|
||||||
|
with file.open() as f:
|
||||||
|
resultats = analyser_resultats(f)
|
||||||
|
|
||||||
|
if not resultats:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if resultats_commune := session.execute(
|
||||||
|
select(ResultatsCommune).filter_by(commune_id=com_code)).scalar_one_or_none():
|
||||||
|
resultats_commune.inscrits = resultats["inscrits"]
|
||||||
|
resultats_commune.abstentions = resultats["abstentions"]
|
||||||
|
resultats_commune.votants = resultats["votants"]
|
||||||
|
resultats_commune.blancs = resultats["blancs"]
|
||||||
|
resultats_commune.nuls = resultats["nuls"]
|
||||||
|
resultats_commune.exprimes = resultats["exprimes"]
|
||||||
|
else:
|
||||||
|
resultats_commune = ResultatsCommune(
|
||||||
|
commune_id=com_code,
|
||||||
|
inscrits=resultats["inscrits"],
|
||||||
|
abstentions=resultats["abstentions"],
|
||||||
|
votants=resultats["votants"],
|
||||||
|
blancs=resultats["blancs"],
|
||||||
|
nuls=resultats["nuls"],
|
||||||
|
exprimes=resultats["exprimes"],
|
||||||
|
)
|
||||||
|
session.add(resultats_commune)
|
||||||
|
|
||||||
|
for voix_liste in resultats["resultats_par_liste"]:
|
||||||
|
if voix_liste_commune := session.execute(
|
||||||
|
select(VoixListeCommune).join(Liste).filter_by(nom_majuscules=voix_liste["nom"].upper())
|
||||||
|
).scalar_one_or_none():
|
||||||
|
voix_liste_commune.voix = voix_liste["voix"]
|
||||||
|
else:
|
||||||
|
liste = session.execute(select(Liste).filter_by(nom_majuscules=voix_liste["nom"].upper())) \
|
||||||
|
.scalar_one()
|
||||||
|
voix_liste_commune = VoixListeCommune(liste_id=liste.id, voix=voix_liste["voix"])
|
||||||
|
session.add(voix_liste_commune)
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def analyser_resultats(file) -> dict:
|
||||||
|
parsed_data = {}
|
||||||
|
|
||||||
|
soup = BeautifulSoup(file, 'html.parser')
|
||||||
|
tables = soup.find_all('table')
|
||||||
|
|
||||||
|
for table in tables:
|
||||||
|
if table.find('th', text=re.compile("Voix")):
|
||||||
|
resultats_par_liste = []
|
||||||
|
parsed_data['resultats_par_liste'] = resultats_par_liste
|
||||||
|
|
||||||
|
tbody = table.tbody
|
||||||
|
for line in tbody.find_all('tr'):
|
||||||
|
cells = line.find_all('td')
|
||||||
|
if len(cells) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
liste = {}
|
||||||
|
resultats_par_liste.append(liste)
|
||||||
|
|
||||||
|
liste['nom'] = cells[0].string
|
||||||
|
liste['voix'] = int(cells[1].string.replace(" ", ""))
|
||||||
|
elif table.find('td', text=re.compile("Inscrits")):
|
||||||
|
tbody = table.tbody
|
||||||
|
for line in tbody.find_all('tr'):
|
||||||
|
cells = line.find_all('td')
|
||||||
|
if len(cells) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
nom = cells[0].string
|
||||||
|
number = int(cells[1].string.replace(" ", ""))
|
||||||
|
match nom:
|
||||||
|
case "Inscrits":
|
||||||
|
parsed_data["inscrits"] = number
|
||||||
|
case "Abstentions":
|
||||||
|
parsed_data["abstentions"] = number
|
||||||
|
case "Votants":
|
||||||
|
parsed_data["votants"] = number
|
||||||
|
case "Blancs":
|
||||||
|
parsed_data["blancs"] = number
|
||||||
|
case "Nuls":
|
||||||
|
parsed_data["nuls"] = number
|
||||||
|
case "Exprimés":
|
||||||
|
parsed_data["exprimes"] = number
|
||||||
|
case _:
|
||||||
|
print(f"Unknown cell: {nom}")
|
||||||
|
|
||||||
|
return parsed_data
|
||||||
|
|
||||||
|
|
||||||
|
def run(engine: Engine) -> None:
|
||||||
|
importer_resultats_france(engine)
|
||||||
|
importer_resultats_regions(engine)
|
||||||
|
importer_resultats_departements(engine)
|
||||||
|
importer_resultats_communes(engine)
|
||||||
|
|
||||||
|
analyser_resultats("")
|
|
@ -1,4 +1,5 @@
|
||||||
alembic~=1.13.1
|
alembic~=1.13.1
|
||||||
|
beautifulsoup4~=4.12.3
|
||||||
python-dotenv~=1.0.1
|
python-dotenv~=1.0.1
|
||||||
requests~=2.32.3
|
requests~=2.32.3
|
||||||
SQLAlchemy~=2.0.30
|
SQLAlchemy~=2.0.30
|
||||||
|
|
Loading…
Reference in New Issue