From 273b3fb072c7fb87f4b9b1019e539963ba8d4475 Mon Sep 17 00:00:00 2001 From: Daniel Grams Date: Fri, 13 Nov 2020 23:05:39 +0100 Subject: [PATCH] Internal/analysis (#4) * Codestyle Black * Flake8 * Test coverage --- .flake8 | 14 + .github/workflows/lint.yml | 12 + .pre-commit-config.yaml | 10 + .travis.yml | 4 +- .vscode/settings.json | 6 +- README.md | 6 +- bootstrap.py | 2 +- doc/development.md | 6 + manage.py | 8 +- migrations/env.py | 22 +- migrations/versions/00daa8c472ba_.py | 49 +- migrations/versions/021f602d9965_.py | 151 +++-- migrations/versions/091deace5f08_.py | 46 +- migrations/versions/0a282a331e35_.py | 51 +- migrations/versions/27da3ceea723_.py | 71 +- migrations/versions/3c5b34fd1156_.py | 93 ++- migrations/versions/41512b20e07c_.py | 14 +- migrations/versions/4e913af88c33_.py | 19 +- migrations/versions/50337ecd23db_.py | 39 +- migrations/versions/51c47c7f0bdb_.py | 16 +- migrations/versions/5c8457f2eac1_.py | 16 +- migrations/versions/62e071b0da50_.py | 35 +- migrations/versions/67216b6cf293_.py | 29 +- migrations/versions/699c4f6a7fe8_.py | 38 +- migrations/versions/6b7016f73688_.py | 436 ++++++++---- migrations/versions/6be822396123_.py | 57 +- migrations/versions/75c07cb9cfe3_.py | 48 +- migrations/versions/7afc40e11791_.py | 48 +- migrations/versions/8f4df40a36f3_.py | 26 +- migrations/versions/92f37474ad62_.py | 68 +- migrations/versions/975c22ae802b_.py | 60 +- migrations/versions/a336ac384c64_.py | 36 +- migrations/versions/a75bd9c8ad3a_.py | 125 ++-- migrations/versions/a8c662c46047_.py | 14 +- migrations/versions/abf0f671ba27_.py | 30 +- migrations/versions/b128cc637447_.py | 20 +- migrations/versions/b1c05324cc13_.py | 12 +- migrations/versions/bbad7e33a780_.py | 640 +++++++++++------- migrations/versions/cce1284874fa_.py | 16 +- migrations/versions/da63ba1d58b1_.py | 37 +- migrations/versions/dcd0b71650b0_.py | 22 +- migrations/versions/ed6bb2084bbd_.py | 19 +- migrations/versions/f1bc3fa623c7_.py | 53 +- migrations/versions/f71c86333bfb_.py | 22 +- migrations/versions/fd7794ece0b3_.py | 50 +- project/__init__.py | 98 +-- project/access.py | 47 +- project/dateutils.py | 104 ++- project/dbtypes.py | 2 + project/forms/admin_unit.py | 87 ++- project/forms/admin_unit_member.py | 25 +- project/forms/common.py | 79 ++- project/forms/event.py | 242 +++++-- project/forms/event_date.py | 41 +- project/forms/event_place.py | 52 +- project/forms/event_suggestion.py | 143 +++- project/forms/organizer.py | 50 +- project/forms/planing.py | 39 +- project/forms/reference.py | 19 +- project/forms/reference_request.py | 73 +- project/forms/widgets.py | 69 +- project/i10n.py | 53 +- project/init_data.py | 19 +- project/jinja_filters.py | 46 +- project/jsonld.py | 29 +- project/models.py | 329 +++++---- project/oauth.py | 11 +- project/scrape/scrape_fp.py | 176 +++-- project/scrape/scrape_hi.py | 186 ++--- project/services/admin_unit.py | 36 +- project/services/event.py | 108 ++- project/services/event_search.py | 35 +- project/services/event_suggestion.py | 10 +- project/services/location.py | 12 +- project/services/organizer.py | 21 +- project/services/place.py | 25 +- project/services/reference.py | 40 +- project/services/user.py | 12 +- project/static/jquery.recurrenceinput.js | 2 +- project/static/site.js | 2 +- project/utils.py | 6 +- project/views/admin.py | 16 +- project/views/admin_unit.py | 51 +- project/views/admin_unit_member.py | 61 +- project/views/admin_unit_member_invitation.py | 99 +-- project/views/api.py | 22 +- project/views/event.py | 185 +++-- project/views/event_date.py | 40 +- project/views/event_place.py | 71 +- project/views/event_suggestion.py | 74 +- project/views/image.py | 5 +- project/views/manage.py | 184 +++-- project/views/organizer.py | 70 +- project/views/planing.py | 21 +- project/views/reference.py | 104 ++- project/views/reference_request.py | 95 ++- project/views/reference_request_review.py | 89 ++- project/views/root.py | 21 +- project/views/user.py | 13 +- project/views/utils.py | 32 +- project/views/widget.py | 130 +++- requirements.txt | 23 + runtime.txt | 2 +- tests/conftest.py | 5 +- tests/test_app.py | 6 +- 105 files changed, 4119 insertions(+), 2224 deletions(-) create mode 100644 .flake8 create mode 100644 .github/workflows/lint.yml create mode 100644 .pre-commit-config.yaml diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..7663589 --- /dev/null +++ b/.flake8 @@ -0,0 +1,14 @@ +[flake8] +extend-ignore = E501, E203 +exclude = + .git, + .github, + .pytest_cache, + .vscode, + __pycache__, + doc, + env, + tmp +per-file-ignores = + __init__.py: F401, E402 + migrations/*: F401, E402 \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..a1b4ae0 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,12 @@ +name: Lint + +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - uses: psf/black@stable + - uses: TrueBrain/actions-flake8@v1.4.1 \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..65d80a7 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,10 @@ +repos: + - repo: https://github.com/psf/black + rev: stable + hooks: + - id: black + language_version: python3.7 + - repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.4 + hooks: + - id: flake8 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 9385183..9c7b602 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,4 +15,6 @@ before_script: - psql -c 'create database gsevpt_tests;' -U postgres - psql -c 'create extension postgis;' -U postgres -d gsevpt_tests script: - - pytest + - pytest --cov=project +after_success: + — coveralls diff --git a/.vscode/settings.json b/.vscode/settings.json index de66823..7f35355 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,7 @@ { - "python.pythonPath": "/Users/daniel/Projects/gsevpt/env/bin/python3" + "python.pythonPath": "/Users/daniel/Projects/gsevpt/env/bin/python3", + "python.formatting.provider": "black", + "python.linting.enabled": true, + "python.linting.pylintEnabled": false, + "python.linting.flake8Enabled": true } \ No newline at end of file diff --git a/README.md b/README.md index e7a67c9..8b1b313 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -[![Build Status](https://travis-ci.com/DanielGrams/gsevpt.svg?branch=master)](https://travis-ci.com/DanielGrams/gsevpt) - # Goslar Event Prototype +[![Build Status](https://travis-ci.com/DanielGrams/gsevpt.svg?branch=master)](https://travis-ci.com/DanielGrams/gsevpt) [![Coverage Status](https://coveralls.io/repos/github/DanielGrams/gsevpt/badge.svg?branch=master)](https://coveralls.io/github/DanielGrams/gsevpt?branch=master) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) + Website prototype using Python, Flask and Postgres running on Heroku. ## Automatic Deployment @@ -67,4 +67,4 @@ Create `.env` file in the root directory or pass as environment variables. ## Development -[Development](doc/development.md) \ No newline at end of file +[Development](doc/development.md) diff --git a/bootstrap.py b/bootstrap.py index c3bbcfc..b4ae769 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -1 +1 @@ -from project import app \ No newline at end of file +from project import app # noqa: F401 diff --git a/doc/development.md b/doc/development.md index c9834c0..01067bd 100644 --- a/doc/development.md +++ b/doc/development.md @@ -15,6 +15,12 @@ psql -c 'create extension postgis;' -d gsevpt_tests -U postgres pytest ``` +With coverage: + +```sh +pytest --cov-report=html --cov=project +``` + ## Database ### Create new revision diff --git a/manage.py b/manage.py index 7d0d73c..9413b63 100644 --- a/manage.py +++ b/manage.py @@ -1,11 +1,11 @@ -from flask_script import Manager, Command +from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from project import app, db migrate = Migrate(app, db) manager = Manager(app) -manager.add_command('db', MigrateCommand) +manager.add_command("db", MigrateCommand) -if __name__ == '__main__': - manager.run() \ No newline at end of file +if __name__ == "__main__": + manager.run() diff --git a/migrations/env.py b/migrations/env.py index 9452179..b896f2c 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -15,17 +15,19 @@ config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') +logger = logging.getLogger("alembic.env") # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata from flask import current_app + config.set_main_option( - 'sqlalchemy.url', - str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%')) -target_metadata = current_app.extensions['migrate'].db.metadata + "sqlalchemy.url", + str(current_app.extensions["migrate"].db.engine.url).replace("%", "%%"), +) +target_metadata = current_app.extensions["migrate"].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -46,9 +48,7 @@ def run_migrations_offline(): """ url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, target_metadata=target_metadata, literal_binds=True - ) + context.configure(url=url, target_metadata=target_metadata, literal_binds=True) with context.begin_transaction(): context.run_migrations() @@ -66,15 +66,15 @@ def run_migrations_online(): # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): + if getattr(config.cmd_opts, "autogenerate", False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] - logger.info('No changes in schema detected.') + logger.info("No changes in schema detected.") connectable = engine_from_config( config.get_section(config.config_ini_section), - prefix='sqlalchemy.', + prefix="sqlalchemy.", poolclass=pool.NullPool, ) @@ -83,7 +83,7 @@ def run_migrations_online(): connection=connection, target_metadata=target_metadata, process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args + **current_app.extensions["migrate"].configure_args ) with context.begin_transaction(): diff --git a/migrations/versions/00daa8c472ba_.py b/migrations/versions/00daa8c472ba_.py index 52fa362..900bbac 100644 --- a/migrations/versions/00daa8c472ba_.py +++ b/migrations/versions/00daa8c472ba_.py @@ -12,31 +12,50 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '00daa8c472ba' -down_revision = '50337ecd23db' +revision = "00daa8c472ba" +down_revision = "50337ecd23db" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - #op.drop_table('spatial_ref_sys') - op.drop_constraint('eventsuggestion_event_id_fkey', 'eventsuggestion', type_='foreignkey') - op.create_foreign_key(None, 'eventsuggestion', 'event', ['event_id'], ['id'], ondelete='SET NULL') + # op.drop_table('spatial_ref_sys') + op.drop_constraint( + "eventsuggestion_event_id_fkey", "eventsuggestion", type_="foreignkey" + ) + op.create_foreign_key( + None, "eventsuggestion", "event", ["event_id"], ["id"], ondelete="SET NULL" + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'eventsuggestion', type_='foreignkey') - op.create_foreign_key('eventsuggestion_event_id_fkey', 'eventsuggestion', 'event', ['event_id'], ['id']) - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.drop_constraint(None, "eventsuggestion", type_="foreignkey") + op.create_foreign_key( + "eventsuggestion_event_id_fkey", + "eventsuggestion", + "event", + ["event_id"], + ["id"], + ) + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/021f602d9965_.py b/migrations/versions/021f602d9965_.py index 9f7dcda..48bdae2 100644 --- a/migrations/versions/021f602d9965_.py +++ b/migrations/versions/021f602d9965_.py @@ -12,68 +12,117 @@ from project import dbtypes from project.models import EventRejectionReason, EventReviewStatus # revision identifiers, used by Alembic. -revision = '021f602d9965' -down_revision = '92f37474ad62' +revision = "021f602d9965" +down_revision = "92f37474ad62" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('eventsuggestion', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=False), - sa.Column('start', sa.DateTime(timezone=True), nullable=False), - sa.Column('description', sa.UnicodeText(), nullable=True), - sa.Column('external_link', sa.String(length=255), nullable=True), - sa.Column('review_status', dbtypes.IntegerEnum(EventReviewStatus), nullable=True), - sa.Column('rejection_resaon', dbtypes.IntegerEnum(EventRejectionReason), nullable=True), - sa.Column('contact_name', sa.Unicode(length=255), nullable=False), - sa.Column('contact_email', sa.Unicode(length=255), nullable=True), - sa.Column('contact_phone', sa.Unicode(length=255), nullable=True), - sa.Column('admin_unit_id', sa.Integer(), nullable=False), - sa.Column('event_place_id', sa.Integer(), nullable=True), - sa.Column('event_place_text', sa.Unicode(length=255), nullable=True), - sa.Column('organizer_id', sa.Integer(), nullable=True), - sa.Column('organizer_text', sa.Unicode(length=255), nullable=True), - sa.Column('photo_id', sa.Integer(), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['event_place_id'], ['eventplace.id'], ), - sa.ForeignKeyConstraint(['organizer_id'], ['eventorganizer.id'], ), - sa.ForeignKeyConstraint(['photo_id'], ['image.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventsuggestion", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=False), + sa.Column("start", sa.DateTime(timezone=True), nullable=False), + sa.Column("description", sa.UnicodeText(), nullable=True), + sa.Column("external_link", sa.String(length=255), nullable=True), + sa.Column( + "review_status", dbtypes.IntegerEnum(EventReviewStatus), nullable=True + ), + sa.Column( + "rejection_resaon", dbtypes.IntegerEnum(EventRejectionReason), nullable=True + ), + sa.Column("contact_name", sa.Unicode(length=255), nullable=False), + sa.Column("contact_email", sa.Unicode(length=255), nullable=True), + sa.Column("contact_phone", sa.Unicode(length=255), nullable=True), + sa.Column("admin_unit_id", sa.Integer(), nullable=False), + sa.Column("event_place_id", sa.Integer(), nullable=True), + sa.Column("event_place_text", sa.Unicode(length=255), nullable=True), + sa.Column("organizer_id", sa.Integer(), nullable=True), + sa.Column("organizer_text", sa.Unicode(length=255), nullable=True), + sa.Column("photo_id", sa.Integer(), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["event_place_id"], + ["eventplace.id"], + ), + sa.ForeignKeyConstraint( + ["organizer_id"], + ["eventorganizer.id"], + ), + sa.ForeignKeyConstraint( + ["photo_id"], + ["image.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - #op.drop_table('spatial_ref_sys') - op.drop_constraint('event_contact_id_fkey', 'event', type_='foreignkey') - op.drop_column('event', 'review_status') - op.drop_column('event', 'rejection_resaon') - op.drop_column('event', 'contact_id') - op.drop_column('eventcontact', 'email') - op.drop_column('eventcontact', 'name') - op.drop_column('eventcontact', 'phone') + # op.drop_table('spatial_ref_sys') + op.drop_constraint("event_contact_id_fkey", "event", type_="foreignkey") + op.drop_column("event", "review_status") + op.drop_column("event", "rejection_resaon") + op.drop_column("event", "contact_id") + op.drop_column("eventcontact", "email") + op.drop_column("eventcontact", "name") + op.drop_column("eventcontact", "phone") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('eventcontact', sa.Column('phone', sa.VARCHAR(length=255), autoincrement=False, nullable=True)) - op.add_column('eventcontact', sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=False)) - op.add_column('eventcontact', sa.Column('email', sa.VARCHAR(length=255), autoincrement=False, nullable=True)) - op.add_column('event', sa.Column('contact_id', sa.INTEGER(), autoincrement=False, nullable=True)) - op.add_column('event', sa.Column('rejection_resaon', sa.INTEGER(), autoincrement=False, nullable=True)) - op.add_column('event', sa.Column('review_status', sa.INTEGER(), autoincrement=False, nullable=True)) - op.create_foreign_key('event_contact_id_fkey', 'event', 'eventcontact', ['contact_id'], ['id']) - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.add_column( + "eventcontact", + sa.Column("phone", sa.VARCHAR(length=255), autoincrement=False, nullable=True), ) - op.drop_table('eventsuggestion') + op.add_column( + "eventcontact", + sa.Column("name", sa.VARCHAR(length=255), autoincrement=False, nullable=False), + ) + op.add_column( + "eventcontact", + sa.Column("email", sa.VARCHAR(length=255), autoincrement=False, nullable=True), + ) + op.add_column( + "event", + sa.Column("contact_id", sa.INTEGER(), autoincrement=False, nullable=True), + ) + op.add_column( + "event", + sa.Column("rejection_resaon", sa.INTEGER(), autoincrement=False, nullable=True), + ) + op.add_column( + "event", + sa.Column("review_status", sa.INTEGER(), autoincrement=False, nullable=True), + ) + op.create_foreign_key( + "event_contact_id_fkey", "event", "eventcontact", ["contact_id"], ["id"] + ) + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), + ) + op.drop_table("eventsuggestion") # ### end Alembic commands ### diff --git a/migrations/versions/091deace5f08_.py b/migrations/versions/091deace5f08_.py index c25ec91..3eee5eb 100644 --- a/migrations/versions/091deace5f08_.py +++ b/migrations/versions/091deace5f08_.py @@ -8,14 +8,12 @@ Create Date: 2020-10-02 09:29:12.932229 from alembic import op import sqlalchemy as sa from sqlalchemy.sql import text -import sqlalchemy_utils -from project import dbtypes from geoalchemy2.types import Geometry # revision identifiers, used by Alembic. -revision = '091deace5f08' -down_revision = '6b7016f73688' +revision = "091deace5f08" +down_revision = "6b7016f73688" branch_labels = None depends_on = None @@ -26,21 +24,39 @@ def upgrade(): bind.execute(text("create extension if not exists postgis;")) # ### commands auto generated by Alembic - please adjust! ### - #op.drop_table('spatial_ref_sys') - op.add_column('location', sa.Column('coordinate', Geometry(geometry_type='POINT', from_text='ST_GeomFromEWKT', name='geometry'), nullable=True)) + # op.drop_table('spatial_ref_sys') + op.add_column( + "location", + sa.Column( + "coordinate", + Geometry( + geometry_type="POINT", from_text="ST_GeomFromEWKT", name="geometry" + ), + nullable=True, + ), + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('location', 'coordinate') - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.drop_column("location", "coordinate") + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/0a282a331e35_.py b/migrations/versions/0a282a331e35_.py index 5bbf539..0b05fb9 100644 --- a/migrations/versions/0a282a331e35_.py +++ b/migrations/versions/0a282a331e35_.py @@ -12,35 +12,48 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '0a282a331e35' -down_revision = 'da63ba1d58b1' +revision = "0a282a331e35" +down_revision = "da63ba1d58b1" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - #op.drop_table('spatial_ref_sys') - op.add_column('event', sa.Column('booked_up', sa.Boolean(), nullable=True)) - op.add_column('event', sa.Column('expected_participants', sa.Integer(), nullable=True)) - op.add_column('event', sa.Column('price_info', sa.UnicodeText(), nullable=True)) - op.add_column('event', sa.Column('registration_required', sa.Boolean(), nullable=True)) + # op.drop_table('spatial_ref_sys') + op.add_column("event", sa.Column("booked_up", sa.Boolean(), nullable=True)) + op.add_column( + "event", sa.Column("expected_participants", sa.Integer(), nullable=True) + ) + op.add_column("event", sa.Column("price_info", sa.UnicodeText(), nullable=True)) + op.add_column( + "event", sa.Column("registration_required", sa.Boolean(), nullable=True) + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('event', 'registration_required') - op.drop_column('event', 'price_info') - op.drop_column('event', 'expected_participants') - op.drop_column('event', 'booked_up') - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.drop_column("event", "registration_required") + op.drop_column("event", "price_info") + op.drop_column("event", "expected_participants") + op.drop_column("event", "booked_up") + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/27da3ceea723_.py b/migrations/versions/27da3ceea723_.py index f0759f6..4428dfd 100644 --- a/migrations/versions/27da3ceea723_.py +++ b/migrations/versions/27da3ceea723_.py @@ -8,39 +8,70 @@ Create Date: 2020-11-08 16:14:01.866196 from alembic import op import sqlalchemy as sa import sqlalchemy_utils -from project import dbtypes # revision identifiers, used by Alembic. -revision = '27da3ceea723' -down_revision = '00daa8c472ba' +revision = "27da3ceea723" +down_revision = "00daa8c472ba" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - #op.drop_table('spatial_ref_sys') - op.add_column('adminunit', sa.Column('widget_background_color', sqlalchemy_utils.types.color.ColorType(length=20), nullable=True)) - op.add_column('adminunit', sa.Column('widget_font', sa.Unicode(length=255), nullable=True)) - op.add_column('adminunit', sa.Column('widget_link_color', sqlalchemy_utils.types.color.ColorType(length=20), nullable=True)) - op.add_column('adminunit', sa.Column('widget_primary_color', sqlalchemy_utils.types.color.ColorType(length=20), nullable=True)) + # op.drop_table('spatial_ref_sys') + op.add_column( + "adminunit", + sa.Column( + "widget_background_color", + sqlalchemy_utils.types.color.ColorType(length=20), + nullable=True, + ), + ) + op.add_column( + "adminunit", sa.Column("widget_font", sa.Unicode(length=255), nullable=True) + ) + op.add_column( + "adminunit", + sa.Column( + "widget_link_color", + sqlalchemy_utils.types.color.ColorType(length=20), + nullable=True, + ), + ) + op.add_column( + "adminunit", + sa.Column( + "widget_primary_color", + sqlalchemy_utils.types.color.ColorType(length=20), + nullable=True, + ), + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('adminunit', 'widget_primary_color') - op.drop_column('adminunit', 'widget_link_color') - op.drop_column('adminunit', 'widget_font') - op.drop_column('adminunit', 'widget_background_color') - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.drop_column("adminunit", "widget_primary_color") + op.drop_column("adminunit", "widget_link_color") + op.drop_column("adminunit", "widget_font") + op.drop_column("adminunit", "widget_background_color") + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/3c5b34fd1156_.py b/migrations/versions/3c5b34fd1156_.py index 2212281..354a191 100644 --- a/migrations/versions/3c5b34fd1156_.py +++ b/migrations/versions/3c5b34fd1156_.py @@ -13,49 +13,65 @@ from project import dbtypes from sqlalchemy.ext.declarative import declarative_base # revision identifiers, used by Alembic. -revision = '3c5b34fd1156' -down_revision = '27da3ceea723' +revision = "3c5b34fd1156" +down_revision = "27da3ceea723" branch_labels = None depends_on = None Base = declarative_base() + class Event(Base): - __tablename__ = 'event' + __tablename__ = "event" id = sa.Column(sa.Integer(), primary_key=True) - category_id = sa.Column(sa.Integer, sa.ForeignKey('eventcategory.id'), nullable=False) - category = orm.relationship('EventCategory', uselist=False) - categories = orm.relationship('EventCategory', secondary='event_eventcategories') + category_id = sa.Column( + sa.Integer, sa.ForeignKey("eventcategory.id"), nullable=False + ) + category = orm.relationship("EventCategory", uselist=False) + categories = orm.relationship("EventCategory", secondary="event_eventcategories") + class EventEventCategories(Base): - __tablename__ = 'event_eventcategories' + __tablename__ = "event_eventcategories" id = sa.Column(sa.Integer(), primary_key=True) - event_id = sa.Column(sa.Integer, sa.ForeignKey('event.id'), nullable=False) - category_id = sa.Column(sa.Integer, sa.ForeignKey('eventcategory.id'), nullable=False) + event_id = sa.Column(sa.Integer, sa.ForeignKey("event.id"), nullable=False) + category_id = sa.Column( + sa.Integer, sa.ForeignKey("eventcategory.id"), nullable=False + ) + class EventCategory(Base): - __tablename__ = 'eventcategory' + __tablename__ = "eventcategory" id = sa.Column(sa.Integer(), primary_key=True) name = sa.Column(sa.Unicode(255), nullable=False, unique=True) + def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('event_eventcategories', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('event_id', sa.Integer(), nullable=False), - sa.Column('category_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['category_id'], ['eventcategory.id'], ), - sa.ForeignKeyConstraint(['event_id'], ['event.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "event_eventcategories", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("event_id", sa.Integer(), nullable=False), + sa.Column("category_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["category_id"], + ["eventcategory.id"], + ), + sa.ForeignKeyConstraint( + ["event_id"], + ["event.id"], + ), + sa.PrimaryKeyConstraint("id"), ) migrate_category_to_categories() - #op.drop_table('spatial_ref_sys') - op.drop_constraint('event_category_id_fkey', 'event', type_='foreignkey') - op.drop_column('event', 'category_id') + # op.drop_table('spatial_ref_sys') + op.drop_constraint("event_category_id_fkey", "event", type_="foreignkey") + op.drop_column("event", "category_id") # ### end Alembic commands ### + def migrate_category_to_categories(): bind = op.get_bind() session = orm.Session(bind=bind) @@ -65,18 +81,33 @@ def migrate_category_to_categories(): session.commit() + def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('event', sa.Column('category_id', sa.INTEGER(), autoincrement=False, nullable=False)) - op.create_foreign_key('event_category_id_fkey', 'event', 'eventcategory', ['category_id'], ['id']) - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.add_column( + "event", + sa.Column("category_id", sa.INTEGER(), autoincrement=False, nullable=False), ) - op.drop_table('event_eventcategories') + op.create_foreign_key( + "event_category_id_fkey", "event", "eventcategory", ["category_id"], ["id"] + ) + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), + ) + op.drop_table("event_eventcategories") # ### end Alembic commands ### diff --git a/migrations/versions/41512b20e07c_.py b/migrations/versions/41512b20e07c_.py index 6b14dbb..3e7ecd4 100644 --- a/migrations/versions/41512b20e07c_.py +++ b/migrations/versions/41512b20e07c_.py @@ -12,21 +12,23 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '41512b20e07c' -down_revision = 'fd7794ece0b3' +revision = "41512b20e07c" +down_revision = "fd7794ece0b3" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint('event_event_place_id_fkey', 'event', type_='foreignkey') - op.create_foreign_key(None, 'event', 'eventplace', ['event_place_id'], ['id']) + op.drop_constraint("event_event_place_id_fkey", "event", type_="foreignkey") + op.create_foreign_key(None, "event", "eventplace", ["event_place_id"], ["id"]) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'event', type_='foreignkey') - op.create_foreign_key('event_event_place_id_fkey', 'event', 'place', ['event_place_id'], ['id']) + op.drop_constraint(None, "event", type_="foreignkey") + op.create_foreign_key( + "event_event_place_id_fkey", "event", "place", ["event_place_id"], ["id"] + ) # ### end Alembic commands ### diff --git a/migrations/versions/4e913af88c33_.py b/migrations/versions/4e913af88c33_.py index d5d60f5..df4dea5 100644 --- a/migrations/versions/4e913af88c33_.py +++ b/migrations/versions/4e913af88c33_.py @@ -12,25 +12,26 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '4e913af88c33' -down_revision = '67216b6cf293' +revision = "4e913af88c33" +down_revision = "67216b6cf293" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('analytics', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('key', sa.Unicode(length=255), nullable=True), - sa.Column('value', sa.UnicodeText(), nullable=True), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_table( + "analytics", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("key", sa.Unicode(length=255), nullable=True), + sa.Column("value", sa.UnicodeText(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.PrimaryKeyConstraint("id"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('analytics') + op.drop_table("analytics") # ### end Alembic commands ### diff --git a/migrations/versions/50337ecd23db_.py b/migrations/versions/50337ecd23db_.py index ee914a8..f7879ca 100644 --- a/migrations/versions/50337ecd23db_.py +++ b/migrations/versions/50337ecd23db_.py @@ -12,31 +12,40 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '50337ecd23db' -down_revision = '6be822396123' +revision = "50337ecd23db" +down_revision = "6be822396123" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - #op.drop_table('spatial_ref_sys') - op.add_column('eventsuggestion', sa.Column('event_id', sa.Integer(), nullable=True)) - op.create_foreign_key(None, 'eventsuggestion', 'event', ['event_id'], ['id']) + # op.drop_table('spatial_ref_sys') + op.add_column("eventsuggestion", sa.Column("event_id", sa.Integer(), nullable=True)) + op.create_foreign_key(None, "eventsuggestion", "event", ["event_id"], ["id"]) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'eventsuggestion', type_='foreignkey') - op.drop_column('eventsuggestion', 'event_id') - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.drop_constraint(None, "eventsuggestion", type_="foreignkey") + op.drop_column("eventsuggestion", "event_id") + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/51c47c7f0bdb_.py b/migrations/versions/51c47c7f0bdb_.py index 6ffbcb4..326a588 100644 --- a/migrations/versions/51c47c7f0bdb_.py +++ b/migrations/versions/51c47c7f0bdb_.py @@ -7,26 +7,26 @@ Create Date: 2020-09-29 15:38:44.033998 """ from alembic import op import sqlalchemy as sa -import sqlalchemy_utils -from project import dbtypes # revision identifiers, used by Alembic. -revision = '51c47c7f0bdb' -down_revision = '7afc40e11791' +revision = "51c47c7f0bdb" +down_revision = "7afc40e11791" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('featuredevent', sa.Column('admin_unit_id', sa.Integer(), nullable=False)) - op.create_foreign_key(None, 'featuredevent', 'adminunit', ['admin_unit_id'], ['id']) + op.add_column( + "featuredevent", sa.Column("admin_unit_id", sa.Integer(), nullable=False) + ) + op.create_foreign_key(None, "featuredevent", "adminunit", ["admin_unit_id"], ["id"]) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'featuredevent', type_='foreignkey') - op.drop_column('featuredevent', 'admin_unit_id') + op.drop_constraint(None, "featuredevent", type_="foreignkey") + op.drop_column("featuredevent", "admin_unit_id") # ### end Alembic commands ### diff --git a/migrations/versions/5c8457f2eac1_.py b/migrations/versions/5c8457f2eac1_.py index e1a75bf..ef5b2f7 100644 --- a/migrations/versions/5c8457f2eac1_.py +++ b/migrations/versions/5c8457f2eac1_.py @@ -7,26 +7,26 @@ Create Date: 2020-07-13 19:01:04.770613 """ from alembic import op import sqlalchemy as sa -import sqlalchemy_utils -from project import dbtypes # revision identifiers, used by Alembic. -revision = '5c8457f2eac1' -down_revision = 'ed6bb2084bbd' +revision = "5c8457f2eac1" +down_revision = "ed6bb2084bbd" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('event', sa.Column('end', sa.DateTime(timezone=True), nullable=True)) - op.add_column('event', sa.Column('start', sa.DateTime(timezone=True), nullable=True)) + op.add_column("event", sa.Column("end", sa.DateTime(timezone=True), nullable=True)) + op.add_column( + "event", sa.Column("start", sa.DateTime(timezone=True), nullable=True) + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('event', 'start') - op.drop_column('event', 'end') + op.drop_column("event", "start") + op.drop_column("event", "end") # ### end Alembic commands ### diff --git a/migrations/versions/62e071b0da50_.py b/migrations/versions/62e071b0da50_.py index e3b7879..e447b1c 100644 --- a/migrations/versions/62e071b0da50_.py +++ b/migrations/versions/62e071b0da50_.py @@ -12,29 +12,36 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '62e071b0da50' -down_revision = 'dcd0b71650b0' +revision = "62e071b0da50" +down_revision = "dcd0b71650b0" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.alter_column('eventorganizer', 'name', - existing_type=sa.VARCHAR(length=255), - nullable=False) - op.create_unique_constraint(None, 'eventorganizer', ['name', 'admin_unit_id']) - op.drop_column('eventorganizer', 'org_name') - op.create_unique_constraint(None, 'eventplace', ['name', 'organizer_id', 'admin_unit_id']) + op.alter_column( + "eventorganizer", "name", existing_type=sa.VARCHAR(length=255), nullable=False + ) + op.create_unique_constraint(None, "eventorganizer", ["name", "admin_unit_id"]) + op.drop_column("eventorganizer", "org_name") + op.create_unique_constraint( + None, "eventplace", ["name", "organizer_id", "admin_unit_id"] + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'eventplace', type_='unique') - op.add_column('eventorganizer', sa.Column('org_name', sa.VARCHAR(length=255), autoincrement=False, nullable=True)) - op.drop_constraint(None, 'eventorganizer', type_='unique') - op.alter_column('eventorganizer', 'name', - existing_type=sa.VARCHAR(length=255), - nullable=True) + op.drop_constraint(None, "eventplace", type_="unique") + op.add_column( + "eventorganizer", + sa.Column( + "org_name", sa.VARCHAR(length=255), autoincrement=False, nullable=True + ), + ) + op.drop_constraint(None, "eventorganizer", type_="unique") + op.alter_column( + "eventorganizer", "name", existing_type=sa.VARCHAR(length=255), nullable=True + ) # ### end Alembic commands ### diff --git a/migrations/versions/67216b6cf293_.py b/migrations/versions/67216b6cf293_.py index 19c0138..fbb69d1 100644 --- a/migrations/versions/67216b6cf293_.py +++ b/migrations/versions/67216b6cf293_.py @@ -7,29 +7,40 @@ Create Date: 2020-08-01 15:43:11.377833 """ from alembic import op import sqlalchemy as sa -import sqlalchemy_utils from project import dbtypes from project.models import EventRejectionReason, EventReviewStatus # revision identifiers, used by Alembic. -revision = '67216b6cf293' -down_revision = 'a336ac384c64' +revision = "67216b6cf293" +down_revision = "a336ac384c64" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('event', sa.Column('rejection_resaon', dbtypes.IntegerEnum(EventRejectionReason), nullable=True)) - op.add_column('event', sa.Column('review_status', dbtypes.IntegerEnum(EventReviewStatus), nullable=True)) - op.drop_column('event', 'verified') + op.add_column( + "event", + sa.Column( + "rejection_resaon", dbtypes.IntegerEnum(EventRejectionReason), nullable=True + ), + ) + op.add_column( + "event", + sa.Column( + "review_status", dbtypes.IntegerEnum(EventReviewStatus), nullable=True + ), + ) + op.drop_column("event", "verified") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('event', sa.Column('verified', sa.BOOLEAN(), autoincrement=False, nullable=True)) - op.drop_column('event', 'review_status') - op.drop_column('event', 'rejection_resaon') + op.add_column( + "event", sa.Column("verified", sa.BOOLEAN(), autoincrement=False, nullable=True) + ) + op.drop_column("event", "review_status") + op.drop_column("event", "rejection_resaon") # ### end Alembic commands ### diff --git a/migrations/versions/699c4f6a7fe8_.py b/migrations/versions/699c4f6a7fe8_.py index 5637a68..b75cde8 100644 --- a/migrations/versions/699c4f6a7fe8_.py +++ b/migrations/versions/699c4f6a7fe8_.py @@ -12,31 +12,37 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '699c4f6a7fe8' -down_revision = 'b1c05324cc13' +revision = "699c4f6a7fe8" +down_revision = "b1c05324cc13" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('eventorganizer', sa.Column('admin_unit_id', sa.Integer(), nullable=True)) - op.create_foreign_key(None, 'eventorganizer', 'adminunit', ['admin_unit_id'], ['id']) - op.add_column('eventplace', sa.Column('admin_unit_id', sa.Integer(), nullable=True)) - op.add_column('eventplace', sa.Column('organizer_id', sa.Integer(), nullable=True)) - op.add_column('eventplace', sa.Column('public', sa.Boolean(), nullable=True)) - op.create_foreign_key(None, 'eventplace', 'eventorganizer', ['organizer_id'], ['id']) - op.create_foreign_key(None, 'eventplace', 'adminunit', ['admin_unit_id'], ['id']) + op.add_column( + "eventorganizer", sa.Column("admin_unit_id", sa.Integer(), nullable=True) + ) + op.create_foreign_key( + None, "eventorganizer", "adminunit", ["admin_unit_id"], ["id"] + ) + op.add_column("eventplace", sa.Column("admin_unit_id", sa.Integer(), nullable=True)) + op.add_column("eventplace", sa.Column("organizer_id", sa.Integer(), nullable=True)) + op.add_column("eventplace", sa.Column("public", sa.Boolean(), nullable=True)) + op.create_foreign_key( + None, "eventplace", "eventorganizer", ["organizer_id"], ["id"] + ) + op.create_foreign_key(None, "eventplace", "adminunit", ["admin_unit_id"], ["id"]) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'eventplace', type_='foreignkey') - op.drop_constraint(None, 'eventplace', type_='foreignkey') - op.drop_column('eventplace', 'public') - op.drop_column('eventplace', 'organizer_id') - op.drop_column('eventplace', 'admin_unit_id') - op.drop_constraint(None, 'eventorganizer', type_='foreignkey') - op.drop_column('eventorganizer', 'admin_unit_id') + op.drop_constraint(None, "eventplace", type_="foreignkey") + op.drop_constraint(None, "eventplace", type_="foreignkey") + op.drop_column("eventplace", "public") + op.drop_column("eventplace", "organizer_id") + op.drop_column("eventplace", "admin_unit_id") + op.drop_constraint(None, "eventorganizer", type_="foreignkey") + op.drop_column("eventorganizer", "admin_unit_id") # ### end Alembic commands ### diff --git a/migrations/versions/6b7016f73688_.py b/migrations/versions/6b7016f73688_.py index dc469a6..d56fb86 100644 --- a/migrations/versions/6b7016f73688_.py +++ b/migrations/versions/6b7016f73688_.py @@ -12,169 +12,321 @@ from project import dbtypes from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. -revision = '6b7016f73688' -down_revision = 'a75bd9c8ad3a' +revision = "6b7016f73688" +down_revision = "a75bd9c8ad3a" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint('event_place_id_fkey', 'event', type_='foreignkey') - op.drop_constraint('event_host_id_fkey', 'event', type_='foreignkey') - op.drop_column('event', 'host_id') - op.drop_column('event', 'place_id') - op.drop_table('eventsuggestiondate') - op.drop_table('place') - op.drop_table('org_or_adminunit') - op.drop_table('actor') - op.drop_table('adminunitorgroles_organizations') - op.drop_table('adminunitorgrole') - op.drop_table('adminunitorg') - op.drop_table('orgmemberroles_members') - op.drop_table('orgmember') - op.drop_table('organization') - op.drop_table('eventsuggestion') - op.drop_table('orgmemberrole') + op.drop_constraint("event_place_id_fkey", "event", type_="foreignkey") + op.drop_constraint("event_host_id_fkey", "event", type_="foreignkey") + op.drop_column("event", "host_id") + op.drop_column("event", "place_id") + op.drop_table("eventsuggestiondate") + op.drop_table("place") + op.drop_table("org_or_adminunit") + op.drop_table("actor") + op.drop_table("adminunitorgroles_organizations") + op.drop_table("adminunitorgrole") + op.drop_table("adminunitorg") + op.drop_table("orgmemberroles_members") + op.drop_table("orgmember") + op.drop_table("organization") + op.drop_table("eventsuggestion") + op.drop_table("orgmemberrole") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('event', sa.Column('place_id', sa.INTEGER(), autoincrement=False, nullable=True)) - op.add_column('event', sa.Column('host_id', sa.INTEGER(), autoincrement=False, nullable=True)) - op.create_foreign_key('event_host_id_fkey', 'event', 'org_or_adminunit', ['host_id'], ['id']) - op.create_foreign_key('event_place_id_fkey', 'event', 'place', ['place_id'], ['id']) - op.create_table('orgmemberroles_members', - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('member_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('role_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.ForeignKeyConstraint(['member_id'], ['orgmember.id'], name='orgmemberroles_members_member_id_fkey'), - sa.ForeignKeyConstraint(['role_id'], ['orgmemberrole.id'], name='orgmemberroles_members_role_id_fkey'), - sa.PrimaryKeyConstraint('id', name='orgmemberroles_members_pkey') + op.add_column( + "event", sa.Column("place_id", sa.INTEGER(), autoincrement=False, nullable=True) ) - op.create_table('orgmemberrole', - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('name', sa.VARCHAR(length=80), autoincrement=False, nullable=True), - sa.Column('description', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('permissions', sa.TEXT(), autoincrement=False, nullable=True), - sa.PrimaryKeyConstraint('id', name='orgmemberrole_pkey'), - sa.UniqueConstraint('name', name='orgmemberrole_name_key') + op.add_column( + "event", sa.Column("host_id", sa.INTEGER(), autoincrement=False, nullable=True) ) - op.create_table('eventsuggestion', - sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), - sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('eventsuggestion_id_seq'::regclass)"), autoincrement=True, nullable=False), - sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('host_name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('event_name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('description', sa.TEXT(), autoincrement=False, nullable=False), - sa.Column('place_name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('place_street', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('place_postalCode', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('place_city', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('contact_name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('contact_email', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('external_link', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='eventsuggestion_admin_unit_id_fkey'), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='eventsuggestion_created_by_id_fkey'), - sa.PrimaryKeyConstraint('id', name='eventsuggestion_pkey'), - postgresql_ignore_search_path=False + op.create_foreign_key( + "event_host_id_fkey", "event", "org_or_adminunit", ["host_id"], ["id"] ) - op.create_table('orgmember', - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('organization_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('user_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], name='orgmember_organization_id_fkey'), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], name='orgmember_user_id_fkey'), - sa.PrimaryKeyConstraint('id', name='orgmember_pkey') + op.create_foreign_key("event_place_id_fkey", "event", "place", ["place_id"], ["id"]) + op.create_table( + "orgmemberroles_members", + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("member_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("role_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint( + ["member_id"], + ["orgmember.id"], + name="orgmemberroles_members_member_id_fkey", + ), + sa.ForeignKeyConstraint( + ["role_id"], + ["orgmemberrole.id"], + name="orgmemberroles_members_role_id_fkey", + ), + sa.PrimaryKeyConstraint("id", name="orgmemberroles_members_pkey"), ) - op.create_table('adminunitorg', - sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('adminunitorg_id_seq'::regclass)"), autoincrement=True, nullable=False), - sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('organization_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='adminunitorg_admin_unit_id_fkey'), - sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], name='adminunitorg_organization_id_fkey'), - sa.PrimaryKeyConstraint('id', name='adminunitorg_pkey'), - postgresql_ignore_search_path=False + op.create_table( + "orgmemberrole", + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("name", sa.VARCHAR(length=80), autoincrement=False, nullable=True), + sa.Column( + "description", sa.VARCHAR(length=255), autoincrement=False, nullable=True + ), + sa.Column("permissions", sa.TEXT(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint("id", name="orgmemberrole_pkey"), + sa.UniqueConstraint("name", name="orgmemberrole_name_key"), ) - op.create_table('adminunitorgroles_organizations', - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('admin_unit_org_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('role_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.ForeignKeyConstraint(['admin_unit_org_id'], ['adminunitorg.id'], name='adminunitorgroles_organizations_admin_unit_org_id_fkey'), - sa.ForeignKeyConstraint(['role_id'], ['adminunitorgrole.id'], name='adminunitorgroles_organizations_role_id_fkey'), - sa.PrimaryKeyConstraint('id', name='adminunitorgroles_organizations_pkey') + op.create_table( + "eventsuggestion", + sa.Column( + "created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True + ), + sa.Column( + "id", + sa.INTEGER(), + server_default=sa.text("nextval('eventsuggestion_id_seq'::regclass)"), + autoincrement=True, + nullable=False, + ), + sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "host_name", sa.VARCHAR(length=255), autoincrement=False, nullable=False + ), + sa.Column( + "event_name", sa.VARCHAR(length=255), autoincrement=False, nullable=False + ), + sa.Column("description", sa.TEXT(), autoincrement=False, nullable=False), + sa.Column( + "place_name", sa.VARCHAR(length=255), autoincrement=False, nullable=False + ), + sa.Column( + "place_street", sa.VARCHAR(length=255), autoincrement=False, nullable=True + ), + sa.Column( + "place_postalCode", + sa.VARCHAR(length=255), + autoincrement=False, + nullable=False, + ), + sa.Column( + "place_city", sa.VARCHAR(length=255), autoincrement=False, nullable=False + ), + sa.Column( + "contact_name", sa.VARCHAR(length=255), autoincrement=False, nullable=False + ), + sa.Column( + "contact_email", sa.VARCHAR(length=255), autoincrement=False, nullable=False + ), + sa.Column( + "external_link", sa.VARCHAR(length=255), autoincrement=False, nullable=True + ), + sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + name="eventsuggestion_admin_unit_id_fkey", + ), + sa.ForeignKeyConstraint( + ["created_by_id"], ["user.id"], name="eventsuggestion_created_by_id_fkey" + ), + sa.PrimaryKeyConstraint("id", name="eventsuggestion_pkey"), + postgresql_ignore_search_path=False, ) - op.create_table('organization', - sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), - sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('organization_id_seq'::regclass)"), autoincrement=True, nullable=False), - sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('legal_name', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('location_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('logo_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('url', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('email', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('phone', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('fax', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('short_name', sa.VARCHAR(length=100), autoincrement=False, nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='organization_created_by_id_fkey'), - sa.ForeignKeyConstraint(['location_id'], ['location.id'], name='organization_location_id_fkey'), - sa.ForeignKeyConstraint(['logo_id'], ['image.id'], name='organization_logo_id_fkey'), - sa.PrimaryKeyConstraint('id', name='organization_pkey'), - sa.UniqueConstraint('name', name='organization_name_key'), - sa.UniqueConstraint('short_name', name='organization_short_name_key'), - postgresql_ignore_search_path=False + op.create_table( + "orgmember", + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("organization_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("user_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint( + ["organization_id"], + ["organization.id"], + name="orgmember_organization_id_fkey", + ), + sa.ForeignKeyConstraint( + ["user_id"], ["user.id"], name="orgmember_user_id_fkey" + ), + sa.PrimaryKeyConstraint("id", name="orgmember_pkey"), ) - op.create_table('adminunitorgrole', - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('name', sa.VARCHAR(length=80), autoincrement=False, nullable=True), - sa.Column('description', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('permissions', sa.TEXT(), autoincrement=False, nullable=True), - sa.PrimaryKeyConstraint('id', name='adminunitorgrole_pkey'), - sa.UniqueConstraint('name', name='adminunitorgrole_name_key') + op.create_table( + "adminunitorg", + sa.Column( + "id", + sa.INTEGER(), + server_default=sa.text("nextval('adminunitorg_id_seq'::regclass)"), + autoincrement=True, + nullable=False, + ), + sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("organization_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint( + ["admin_unit_id"], ["adminunit.id"], name="adminunitorg_admin_unit_id_fkey" + ), + sa.ForeignKeyConstraint( + ["organization_id"], + ["organization.id"], + name="adminunitorg_organization_id_fkey", + ), + sa.PrimaryKeyConstraint("id", name="adminunitorg_pkey"), + postgresql_ignore_search_path=False, ) - op.create_table('actor', - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('user_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('organization_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='actor_admin_unit_id_fkey'), - sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], name='actor_organization_id_fkey'), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], name='actor_user_id_fkey'), - sa.PrimaryKeyConstraint('id', name='actor_pkey'), - sa.UniqueConstraint('user_id', 'organization_id', 'admin_unit_id', name='actor_user_id_organization_id_admin_unit_id_key') + op.create_table( + "adminunitorgroles_organizations", + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column( + "admin_unit_org_id", sa.INTEGER(), autoincrement=False, nullable=True + ), + sa.Column("role_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_org_id"], + ["adminunitorg.id"], + name="adminunitorgroles_organizations_admin_unit_org_id_fkey", + ), + sa.ForeignKeyConstraint( + ["role_id"], + ["adminunitorgrole.id"], + name="adminunitorgroles_organizations_role_id_fkey", + ), + sa.PrimaryKeyConstraint("id", name="adminunitorgroles_organizations_pkey"), ) - op.create_table('org_or_adminunit', - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('organization_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.CheckConstraint('NOT ((organization_id IS NULL) AND (admin_unit_id IS NULL))', name='org_or_adminunit_check'), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='org_or_adminunit_admin_unit_id_fkey'), - sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], name='org_or_adminunit_organization_id_fkey'), - sa.PrimaryKeyConstraint('id', name='org_or_adminunit_pkey'), - sa.UniqueConstraint('organization_id', 'admin_unit_id', name='org_or_adminunit_organization_id_admin_unit_id_key') + op.create_table( + "organization", + sa.Column( + "created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True + ), + sa.Column( + "id", + sa.INTEGER(), + server_default=sa.text("nextval('organization_id_seq'::regclass)"), + autoincrement=True, + nullable=False, + ), + sa.Column("name", sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column( + "legal_name", sa.VARCHAR(length=255), autoincrement=False, nullable=True + ), + sa.Column("location_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("logo_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("url", sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("email", sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column("phone", sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column("fax", sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column( + "short_name", sa.VARCHAR(length=100), autoincrement=False, nullable=True + ), + sa.ForeignKeyConstraint( + ["created_by_id"], ["user.id"], name="organization_created_by_id_fkey" + ), + sa.ForeignKeyConstraint( + ["location_id"], ["location.id"], name="organization_location_id_fkey" + ), + sa.ForeignKeyConstraint( + ["logo_id"], ["image.id"], name="organization_logo_id_fkey" + ), + sa.PrimaryKeyConstraint("id", name="organization_pkey"), + sa.UniqueConstraint("name", name="organization_name_key"), + sa.UniqueConstraint("short_name", name="organization_short_name_key"), + postgresql_ignore_search_path=False, ) - op.create_table('place', - sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('location_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('photo_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('url', sa.VARCHAR(length=255), autoincrement=False, nullable=True), - sa.Column('description', sa.TEXT(), autoincrement=False, nullable=True), - sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='place_created_by_id_fkey'), - sa.ForeignKeyConstraint(['location_id'], ['location.id'], name='place_location_id_fkey'), - sa.ForeignKeyConstraint(['photo_id'], ['image.id'], name='place_photo_id_fkey'), - sa.PrimaryKeyConstraint('id', name='place_pkey') + op.create_table( + "adminunitorgrole", + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("name", sa.VARCHAR(length=80), autoincrement=False, nullable=True), + sa.Column( + "description", sa.VARCHAR(length=255), autoincrement=False, nullable=True + ), + sa.Column("permissions", sa.TEXT(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint("id", name="adminunitorgrole_pkey"), + sa.UniqueConstraint("name", name="adminunitorgrole_name_key"), ) - op.create_table('eventsuggestiondate', - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('event_suggestion_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('start', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), - sa.ForeignKeyConstraint(['event_suggestion_id'], ['eventsuggestion.id'], name='eventsuggestiondate_event_suggestion_id_fkey'), - sa.PrimaryKeyConstraint('id', name='eventsuggestiondate_pkey') + op.create_table( + "actor", + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("user_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("organization_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], ["adminunit.id"], name="actor_admin_unit_id_fkey" + ), + sa.ForeignKeyConstraint( + ["organization_id"], ["organization.id"], name="actor_organization_id_fkey" + ), + sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="actor_user_id_fkey"), + sa.PrimaryKeyConstraint("id", name="actor_pkey"), + sa.UniqueConstraint( + "user_id", + "organization_id", + "admin_unit_id", + name="actor_user_id_organization_id_admin_unit_id_key", + ), + ) + op.create_table( + "org_or_adminunit", + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("organization_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.CheckConstraint( + "NOT ((organization_id IS NULL) AND (admin_unit_id IS NULL))", + name="org_or_adminunit_check", + ), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + name="org_or_adminunit_admin_unit_id_fkey", + ), + sa.ForeignKeyConstraint( + ["organization_id"], + ["organization.id"], + name="org_or_adminunit_organization_id_fkey", + ), + sa.PrimaryKeyConstraint("id", name="org_or_adminunit_pkey"), + sa.UniqueConstraint( + "organization_id", + "admin_unit_id", + name="org_or_adminunit_organization_id_admin_unit_id_key", + ), + ) + op.create_table( + "place", + sa.Column( + "created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True + ), + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("name", sa.VARCHAR(length=255), autoincrement=False, nullable=False), + sa.Column("location_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("photo_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("url", sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column("description", sa.TEXT(), autoincrement=False, nullable=True), + sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], ["user.id"], name="place_created_by_id_fkey" + ), + sa.ForeignKeyConstraint( + ["location_id"], ["location.id"], name="place_location_id_fkey" + ), + sa.ForeignKeyConstraint(["photo_id"], ["image.id"], name="place_photo_id_fkey"), + sa.PrimaryKeyConstraint("id", name="place_pkey"), + ) + op.create_table( + "eventsuggestiondate", + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column( + "event_suggestion_id", sa.INTEGER(), autoincrement=False, nullable=False + ), + sa.Column( + "start", + postgresql.TIMESTAMP(timezone=True), + autoincrement=False, + nullable=False, + ), + sa.ForeignKeyConstraint( + ["event_suggestion_id"], + ["eventsuggestion.id"], + name="eventsuggestiondate_event_suggestion_id_fkey", + ), + sa.PrimaryKeyConstraint("id", name="eventsuggestiondate_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/6be822396123_.py b/migrations/versions/6be822396123_.py index 63d7cfb..083745f 100644 --- a/migrations/versions/6be822396123_.py +++ b/migrations/versions/6be822396123_.py @@ -12,37 +12,54 @@ from project import dbtypes from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. -revision = '6be822396123' -down_revision = '021f602d9965' +revision = "6be822396123" +down_revision = "021f602d9965" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - #op.drop_table('spatial_ref_sys') - op.drop_table('eventcontact') - op.add_column('eventsuggestion', sa.Column('contact_email_notice', sa.Boolean(), nullable=True)) + # op.drop_table('spatial_ref_sys') + op.drop_table("eventcontact") + op.add_column( + "eventsuggestion", + sa.Column("contact_email_notice", sa.Boolean(), nullable=True), + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('eventsuggestion', 'contact_email_notice') - op.create_table('eventcontact', - sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='eventcontact_created_by_id_fkey'), - sa.PrimaryKeyConstraint('id', name='eventcontact_pkey') + op.drop_column("eventsuggestion", "contact_email_notice") + op.create_table( + "eventcontact", + sa.Column( + "created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True + ), + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], ["user.id"], name="eventcontact_created_by_id_fkey" + ), + sa.PrimaryKeyConstraint("id", name="eventcontact_pkey"), ) - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/75c07cb9cfe3_.py b/migrations/versions/75c07cb9cfe3_.py index 5228d41..279dc5e 100644 --- a/migrations/versions/75c07cb9cfe3_.py +++ b/migrations/versions/75c07cb9cfe3_.py @@ -11,35 +11,43 @@ import sqlalchemy_utils # revision identifiers, used by Alembic. -revision = '75c07cb9cfe3' -down_revision = 'abf0f671ba27' +revision = "75c07cb9cfe3" +down_revision = "abf0f671ba27" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('adminunit', sa.Column('email', sa.Unicode(length=255), nullable=True)) - op.add_column('adminunit', sa.Column('location_id', sa.Integer(), nullable=True)) - op.add_column('adminunit', sa.Column('logo_id', sa.Integer(), nullable=True)) - op.add_column('adminunit', sa.Column('phone', sa.Unicode(length=255), nullable=True)) - op.add_column('adminunit', sa.Column('url', sa.String(length=255), nullable=True)) - op.create_foreign_key(None, 'adminunit', 'image', ['logo_id'], ['id']) - op.create_foreign_key(None, 'adminunit', 'location', ['location_id'], ['id']) - op.add_column('organization', sa.Column('email', sa.Unicode(length=255), nullable=True)) - op.add_column('organization', sa.Column('phone', sa.Unicode(length=255), nullable=True)) + op.add_column( + "adminunit", sa.Column("email", sa.Unicode(length=255), nullable=True) + ) + op.add_column("adminunit", sa.Column("location_id", sa.Integer(), nullable=True)) + op.add_column("adminunit", sa.Column("logo_id", sa.Integer(), nullable=True)) + op.add_column( + "adminunit", sa.Column("phone", sa.Unicode(length=255), nullable=True) + ) + op.add_column("adminunit", sa.Column("url", sa.String(length=255), nullable=True)) + op.create_foreign_key(None, "adminunit", "image", ["logo_id"], ["id"]) + op.create_foreign_key(None, "adminunit", "location", ["location_id"], ["id"]) + op.add_column( + "organization", sa.Column("email", sa.Unicode(length=255), nullable=True) + ) + op.add_column( + "organization", sa.Column("phone", sa.Unicode(length=255), nullable=True) + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('organization', 'phone') - op.drop_column('organization', 'email') - op.drop_constraint(None, 'adminunit', type_='foreignkey') - op.drop_constraint(None, 'adminunit', type_='foreignkey') - op.drop_column('adminunit', 'url') - op.drop_column('adminunit', 'phone') - op.drop_column('adminunit', 'logo_id') - op.drop_column('adminunit', 'location_id') - op.drop_column('adminunit', 'email') + op.drop_column("organization", "phone") + op.drop_column("organization", "email") + op.drop_constraint(None, "adminunit", type_="foreignkey") + op.drop_constraint(None, "adminunit", type_="foreignkey") + op.drop_column("adminunit", "url") + op.drop_column("adminunit", "phone") + op.drop_column("adminunit", "logo_id") + op.drop_column("adminunit", "location_id") + op.drop_column("adminunit", "email") # ### end Alembic commands ### diff --git a/migrations/versions/7afc40e11791_.py b/migrations/versions/7afc40e11791_.py index 710cf99..6d951b2 100644 --- a/migrations/versions/7afc40e11791_.py +++ b/migrations/versions/7afc40e11791_.py @@ -7,38 +7,52 @@ Create Date: 2020-09-28 10:38:46.424791 """ from alembic import op import sqlalchemy as sa -import sqlalchemy_utils from project import dbtypes from project.models import FeaturedEventRejectionReason, FeaturedEventReviewStatus # revision identifiers, used by Alembic. -revision = '7afc40e11791' -down_revision = 'a8c662c46047' +revision = "7afc40e11791" +down_revision = "a8c662c46047" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('featuredevent', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('event_id', sa.Integer(), nullable=False), - sa.Column('review_status', dbtypes.IntegerEnum(FeaturedEventReviewStatus), nullable=True), - sa.Column('rejection_resaon', dbtypes.IntegerEnum(FeaturedEventRejectionReason), nullable=True), - sa.Column('rating', sa.Integer(), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['event_id'], ['event.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "featuredevent", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("event_id", sa.Integer(), nullable=False), + sa.Column( + "review_status", + dbtypes.IntegerEnum(FeaturedEventReviewStatus), + nullable=True, + ), + sa.Column( + "rejection_resaon", + dbtypes.IntegerEnum(FeaturedEventRejectionReason), + nullable=True, + ), + sa.Column("rating", sa.Integer(), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["event_id"], + ["event.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.add_column('event', sa.Column('rating', sa.Integer(), nullable=True)) + op.add_column("event", sa.Column("rating", sa.Integer(), nullable=True)) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('event', 'rating') - op.drop_table('featuredevent') + op.drop_column("event", "rating") + op.drop_table("featuredevent") # ### end Alembic commands ### diff --git a/migrations/versions/8f4df40a36f3_.py b/migrations/versions/8f4df40a36f3_.py index 59a4a8c..4316eb7 100644 --- a/migrations/versions/8f4df40a36f3_.py +++ b/migrations/versions/8f4df40a36f3_.py @@ -12,27 +12,31 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '8f4df40a36f3' -down_revision = 'f71c86333bfb' +revision = "8f4df40a36f3" +down_revision = "f71c86333bfb" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('adminunitmemberinvitation', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('admin_unit_id', sa.Integer(), nullable=False), - sa.Column('email', sa.String(length=255), nullable=True), - sa.Column('roles', sa.UnicodeText(), nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('email', 'admin_unit_id') + op.create_table( + "adminunitmemberinvitation", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("admin_unit_id", sa.Integer(), nullable=False), + sa.Column("email", sa.String(length=255), nullable=True), + sa.Column("roles", sa.UnicodeText(), nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("email", "admin_unit_id"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('adminunitmemberinvitation') + op.drop_table("adminunitmemberinvitation") # ### end Alembic commands ### diff --git a/migrations/versions/92f37474ad62_.py b/migrations/versions/92f37474ad62_.py index d3d16f8..4c11377 100644 --- a/migrations/versions/92f37474ad62_.py +++ b/migrations/versions/92f37474ad62_.py @@ -7,41 +7,65 @@ Create Date: 2020-10-18 13:06:47.639083 """ from alembic import op import sqlalchemy as sa -import sqlalchemy_utils -from project import dbtypes -from project.models import EventRejectionReason, EventReviewStatus # revision identifiers, used by Alembic. -revision = '92f37474ad62' -down_revision = '0a282a331e35' +revision = "92f37474ad62" +down_revision = "0a282a331e35" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - #op.drop_table('spatial_ref_sys') - op.drop_constraint('eventplace_name_organizer_id_admin_unit_id_key', 'eventplace', type_='unique') - op.drop_constraint('eventplace_organizer_id_fkey', 'eventplace', type_='foreignkey') - op.drop_column('eventplace', 'public') - op.drop_column('eventplace', 'organizer_id') + # op.drop_table('spatial_ref_sys') + op.drop_constraint( + "eventplace_name_organizer_id_admin_unit_id_key", "eventplace", type_="unique" + ) + op.drop_constraint("eventplace_organizer_id_fkey", "eventplace", type_="foreignkey") + op.drop_column("eventplace", "public") + op.drop_column("eventplace", "organizer_id") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('eventplace', sa.Column('organizer_id', sa.INTEGER(), autoincrement=False, nullable=True)) - op.add_column('eventplace', sa.Column('public', sa.BOOLEAN(), autoincrement=False, nullable=True)) - op.create_foreign_key('eventplace_organizer_id_fkey', 'eventplace', 'eventorganizer', ['organizer_id'], ['id']) - op.create_unique_constraint('eventplace_name_organizer_id_admin_unit_id_key', 'eventplace', ['name', 'organizer_id', 'admin_unit_id']) - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.add_column( + "eventplace", + sa.Column("organizer_id", sa.INTEGER(), autoincrement=False, nullable=True), + ) + op.add_column( + "eventplace", + sa.Column("public", sa.BOOLEAN(), autoincrement=False, nullable=True), + ) + op.create_foreign_key( + "eventplace_organizer_id_fkey", + "eventplace", + "eventorganizer", + ["organizer_id"], + ["id"], + ) + op.create_unique_constraint( + "eventplace_name_organizer_id_admin_unit_id_key", + "eventplace", + ["name", "organizer_id", "admin_unit_id"], + ) + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/975c22ae802b_.py b/migrations/versions/975c22ae802b_.py index eec41c4..8114754 100644 --- a/migrations/versions/975c22ae802b_.py +++ b/migrations/versions/975c22ae802b_.py @@ -12,48 +12,44 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = '975c22ae802b' -down_revision = '5c8457f2eac1' +revision = "975c22ae802b" +down_revision = "5c8457f2eac1" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('eventorganizer', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=True), - sa.Column('org_name', sa.Unicode(length=255), nullable=True), - sa.Column('url', sa.String(length=255), nullable=True), - sa.Column('email', sa.Unicode(length=255), nullable=True), - sa.Column('phone', sa.Unicode(length=255), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventorganizer", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=True), + sa.Column("org_name", sa.Unicode(length=255), nullable=True), + sa.Column("url", sa.String(length=255), nullable=True), + sa.Column("email", sa.Unicode(length=255), nullable=True), + sa.Column("phone", sa.Unicode(length=255), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.add_column('event', sa.Column('organizer_id', sa.Integer(), nullable=True)) - op.alter_column('event', 'host_id', - existing_type=sa.INTEGER(), - nullable=True) - op.alter_column('event', 'place_id', - existing_type=sa.INTEGER(), - nullable=True) - op.create_foreign_key(None, 'event', 'eventorganizer', ['organizer_id'], ['id']) - op.drop_constraint('place_name_key', 'place', type_='unique') + op.add_column("event", sa.Column("organizer_id", sa.Integer(), nullable=True)) + op.alter_column("event", "host_id", existing_type=sa.INTEGER(), nullable=True) + op.alter_column("event", "place_id", existing_type=sa.INTEGER(), nullable=True) + op.create_foreign_key(None, "event", "eventorganizer", ["organizer_id"], ["id"]) + op.drop_constraint("place_name_key", "place", type_="unique") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_unique_constraint('place_name_key', 'place', ['name']) - op.drop_constraint(None, 'event', type_='foreignkey') - op.alter_column('event', 'place_id', - existing_type=sa.INTEGER(), - nullable=False) - op.alter_column('event', 'host_id', - existing_type=sa.INTEGER(), - nullable=False) - op.drop_column('event', 'organizer_id') - op.drop_table('eventorganizer') + op.create_unique_constraint("place_name_key", "place", ["name"]) + op.drop_constraint(None, "event", type_="foreignkey") + op.alter_column("event", "place_id", existing_type=sa.INTEGER(), nullable=False) + op.alter_column("event", "host_id", existing_type=sa.INTEGER(), nullable=False) + op.drop_column("event", "organizer_id") + op.drop_table("eventorganizer") # ### end Alembic commands ### diff --git a/migrations/versions/a336ac384c64_.py b/migrations/versions/a336ac384c64_.py index 7c830c9..6f3413e 100644 --- a/migrations/versions/a336ac384c64_.py +++ b/migrations/versions/a336ac384c64_.py @@ -12,32 +12,36 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'a336ac384c64' -down_revision = '62e071b0da50' +revision = "a336ac384c64" +down_revision = "62e071b0da50" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('eventcontact', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=False), - sa.Column('email', sa.Unicode(length=255), nullable=True), - sa.Column('phone', sa.Unicode(length=255), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventcontact", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=False), + sa.Column("email", sa.Unicode(length=255), nullable=True), + sa.Column("phone", sa.Unicode(length=255), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.add_column('event', sa.Column('contact_id', sa.Integer(), nullable=True)) - op.create_foreign_key(None, 'event', 'eventcontact', ['contact_id'], ['id']) + op.add_column("event", sa.Column("contact_id", sa.Integer(), nullable=True)) + op.create_foreign_key(None, "event", "eventcontact", ["contact_id"], ["id"]) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'event', type_='foreignkey') - op.drop_column('event', 'contact_id') - op.drop_table('eventcontact') + op.drop_constraint(None, "event", type_="foreignkey") + op.drop_column("event", "contact_id") + op.drop_table("eventcontact") # ### end Alembic commands ### diff --git a/migrations/versions/a75bd9c8ad3a_.py b/migrations/versions/a75bd9c8ad3a_.py index 963c246..ce11bca 100644 --- a/migrations/versions/a75bd9c8ad3a_.py +++ b/migrations/versions/a75bd9c8ad3a_.py @@ -7,65 +7,104 @@ Create Date: 2020-09-29 16:53:02.520125 """ from alembic import op import sqlalchemy as sa -import sqlalchemy_utils from project import dbtypes from sqlalchemy.dialects import postgresql -from project.models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus +from project.models import ( + EventReferenceRequestRejectionReason, + EventReferenceRequestReviewStatus, +) # revision identifiers, used by Alembic. -revision = 'a75bd9c8ad3a' -down_revision = '51c47c7f0bdb' +revision = "a75bd9c8ad3a" +down_revision = "51c47c7f0bdb" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('eventreference', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('event_id', sa.Integer(), nullable=False), - sa.Column('admin_unit_id', sa.Integer(), nullable=False), - sa.Column('rating', sa.Integer(), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['event_id'], ['event.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventreference", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("event_id", sa.Integer(), nullable=False), + sa.Column("admin_unit_id", sa.Integer(), nullable=False), + sa.Column("rating", sa.Integer(), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["event_id"], + ["event.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('eventreferencerequest', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('event_id', sa.Integer(), nullable=False), - sa.Column('admin_unit_id', sa.Integer(), nullable=False), - sa.Column('review_status', dbtypes.IntegerEnum(EventReferenceRequestReviewStatus), nullable=True), - sa.Column('rejection_reason', dbtypes.IntegerEnum(EventReferenceRequestRejectionReason), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['event_id'], ['event.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventreferencerequest", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("event_id", sa.Integer(), nullable=False), + sa.Column("admin_unit_id", sa.Integer(), nullable=False), + sa.Column( + "review_status", + dbtypes.IntegerEnum(EventReferenceRequestReviewStatus), + nullable=True, + ), + sa.Column( + "rejection_reason", + dbtypes.IntegerEnum(EventReferenceRequestRejectionReason), + nullable=True, + ), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["event_id"], + ["event.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.drop_table('featuredevent') + op.drop_table("featuredevent") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('featuredevent', - sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), - sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), - sa.Column('event_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('review_status', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('rejection_resaon', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('rating', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='featuredevent_admin_unit_id_fkey'), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='featuredevent_created_by_id_fkey'), - sa.ForeignKeyConstraint(['event_id'], ['event.id'], name='featuredevent_event_id_fkey'), - sa.PrimaryKeyConstraint('id', name='featuredevent_pkey') + op.create_table( + "featuredevent", + sa.Column( + "created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True + ), + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column("event_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("review_status", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("rejection_resaon", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("rating", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint( + ["admin_unit_id"], ["adminunit.id"], name="featuredevent_admin_unit_id_fkey" + ), + sa.ForeignKeyConstraint( + ["created_by_id"], ["user.id"], name="featuredevent_created_by_id_fkey" + ), + sa.ForeignKeyConstraint( + ["event_id"], ["event.id"], name="featuredevent_event_id_fkey" + ), + sa.PrimaryKeyConstraint("id", name="featuredevent_pkey"), ) - op.drop_table('eventreferencerequest') - op.drop_table('eventreference') + op.drop_table("eventreferencerequest") + op.drop_table("eventreference") # ### end Alembic commands ### diff --git a/migrations/versions/a8c662c46047_.py b/migrations/versions/a8c662c46047_.py index 53dc204..670324e 100644 --- a/migrations/versions/a8c662c46047_.py +++ b/migrations/versions/a8c662c46047_.py @@ -12,21 +12,23 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'a8c662c46047' -down_revision = '8f4df40a36f3' +revision = "a8c662c46047" +down_revision = "8f4df40a36f3" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('adminunitmemberrole', sa.Column('title', sa.Unicode(length=255), nullable=True)) - op.add_column('role', sa.Column('title', sa.Unicode(length=255), nullable=True)) + op.add_column( + "adminunitmemberrole", sa.Column("title", sa.Unicode(length=255), nullable=True) + ) + op.add_column("role", sa.Column("title", sa.Unicode(length=255), nullable=True)) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('role', 'title') - op.drop_column('adminunitmemberrole', 'title') + op.drop_column("role", "title") + op.drop_column("adminunitmemberrole", "title") # ### end Alembic commands ### diff --git a/migrations/versions/abf0f671ba27_.py b/migrations/versions/abf0f671ba27_.py index c2dd613..7d464db 100644 --- a/migrations/versions/abf0f671ba27_.py +++ b/migrations/versions/abf0f671ba27_.py @@ -11,29 +11,33 @@ import sqlalchemy_utils # revision identifiers, used by Alembic. -revision = 'abf0f671ba27' -down_revision = 'bbad7e33a780' +revision = "abf0f671ba27" +down_revision = "bbad7e33a780" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('flask_dance_oauth', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('provider', sa.String(length=50), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=False), - sa.Column('token', sqlalchemy_utils.types.json.JSONType(), nullable=False), - sa.Column('provider_user_id', sa.String(length=256), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('provider_user_id') + op.create_table( + "flask_dance_oauth", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("provider", sa.String(length=50), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("token", sqlalchemy_utils.types.json.JSONType(), nullable=False), + sa.Column("provider_user_id", sa.String(length=256), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("provider_user_id"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('flask_dance_oauth') + op.drop_table("flask_dance_oauth") # ### end Alembic commands ### diff --git a/migrations/versions/b128cc637447_.py b/migrations/versions/b128cc637447_.py index 559ad4c..3f0ad95 100644 --- a/migrations/versions/b128cc637447_.py +++ b/migrations/versions/b128cc637447_.py @@ -12,23 +12,27 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'b128cc637447' -down_revision = '41512b20e07c' +revision = "b128cc637447" +down_revision = "41512b20e07c" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('adminunit', sa.Column('fax', sa.Unicode(length=255), nullable=True)) - op.add_column('eventorganizer', sa.Column('fax', sa.Unicode(length=255), nullable=True)) - op.add_column('organization', sa.Column('fax', sa.Unicode(length=255), nullable=True)) + op.add_column("adminunit", sa.Column("fax", sa.Unicode(length=255), nullable=True)) + op.add_column( + "eventorganizer", sa.Column("fax", sa.Unicode(length=255), nullable=True) + ) + op.add_column( + "organization", sa.Column("fax", sa.Unicode(length=255), nullable=True) + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('organization', 'fax') - op.drop_column('eventorganizer', 'fax') - op.drop_column('adminunit', 'fax') + op.drop_column("organization", "fax") + op.drop_column("eventorganizer", "fax") + op.drop_column("adminunit", "fax") # ### end Alembic commands ### diff --git a/migrations/versions/b1c05324cc13_.py b/migrations/versions/b1c05324cc13_.py index 7f357d4..b6e12ba 100644 --- a/migrations/versions/b1c05324cc13_.py +++ b/migrations/versions/b1c05324cc13_.py @@ -12,21 +12,21 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'b1c05324cc13' -down_revision = 'cce1284874fa' +revision = "b1c05324cc13" +down_revision = "cce1284874fa" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_unique_constraint(None, 'adminunit', ['short_name']) - op.create_unique_constraint(None, 'organization', ['short_name']) + op.create_unique_constraint(None, "adminunit", ["short_name"]) + op.create_unique_constraint(None, "organization", ["short_name"]) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'organization', type_='unique') - op.drop_constraint(None, 'adminunit', type_='unique') + op.drop_constraint(None, "organization", type_="unique") + op.drop_constraint(None, "adminunit", type_="unique") # ### end Alembic commands ### diff --git a/migrations/versions/bbad7e33a780_.py b/migrations/versions/bbad7e33a780_.py index b31ed3d..661c020 100644 --- a/migrations/versions/bbad7e33a780_.py +++ b/migrations/versions/bbad7e33a780_.py @@ -1,7 +1,7 @@ """empty message Revision ID: bbad7e33a780 -Revises: +Revises: Create Date: 2020-06-24 21:17:25.548159 """ @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = 'bbad7e33a780' +revision = "bbad7e33a780" down_revision = None branch_labels = None depends_on = None @@ -18,282 +18,420 @@ depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('adminunitmemberrole', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=80), nullable=True), - sa.Column('description', sa.String(length=255), nullable=True), - sa.Column('permissions', sa.UnicodeText(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "adminunitmemberrole", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=80), nullable=True), + sa.Column("description", sa.String(length=255), nullable=True), + sa.Column("permissions", sa.UnicodeText(), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('adminunitorgrole', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=80), nullable=True), - sa.Column('description', sa.String(length=255), nullable=True), - sa.Column('permissions', sa.UnicodeText(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "adminunitorgrole", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=80), nullable=True), + sa.Column("description", sa.String(length=255), nullable=True), + sa.Column("permissions", sa.UnicodeText(), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('eventcategory', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=False), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "eventcategory", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=False), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('orgmemberrole', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=80), nullable=True), - sa.Column('description', sa.String(length=255), nullable=True), - sa.Column('permissions', sa.UnicodeText(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "orgmemberrole", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=80), nullable=True), + sa.Column("description", sa.String(length=255), nullable=True), + sa.Column("permissions", sa.UnicodeText(), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('role', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=80), nullable=True), - sa.Column('description', sa.String(length=255), nullable=True), - sa.Column('permissions', sa.UnicodeText(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "role", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=80), nullable=True), + sa.Column("description", sa.String(length=255), nullable=True), + sa.Column("permissions", sa.UnicodeText(), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('email', sa.String(length=255), nullable=True), - sa.Column('username', sa.String(length=255), nullable=True), - sa.Column('password', sa.String(length=255), nullable=True), - sa.Column('last_login_at', sa.DateTime(), nullable=True), - sa.Column('current_login_at', sa.DateTime(), nullable=True), - sa.Column('last_login_ip', sa.String(length=100), nullable=True), - sa.Column('current_login_ip', sa.String(length=100), nullable=True), - sa.Column('login_count', sa.Integer(), nullable=True), - sa.Column('active', sa.Boolean(), nullable=True), - sa.Column('fs_uniquifier', sa.String(length=255), nullable=True), - sa.Column('confirmed_at', sa.DateTime(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('email') + op.create_table( + "user", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("email", sa.String(length=255), nullable=True), + sa.Column("username", sa.String(length=255), nullable=True), + sa.Column("password", sa.String(length=255), nullable=True), + sa.Column("last_login_at", sa.DateTime(), nullable=True), + sa.Column("current_login_at", sa.DateTime(), nullable=True), + sa.Column("last_login_ip", sa.String(length=100), nullable=True), + sa.Column("current_login_ip", sa.String(length=100), nullable=True), + sa.Column("login_count", sa.Integer(), nullable=True), + sa.Column("active", sa.Boolean(), nullable=True), + sa.Column("fs_uniquifier", sa.String(length=255), nullable=True), + sa.Column("confirmed_at", sa.DateTime(), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("email"), ) - op.create_table('adminunit', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "adminunit", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('image', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('data', sa.LargeBinary(), nullable=True), - sa.Column('encoding_format', sa.String(length=80), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "image", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("data", sa.LargeBinary(), nullable=True), + sa.Column("encoding_format", sa.String(length=80), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('location', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('street', sa.Unicode(length=255), nullable=True), - sa.Column('postalCode', sa.Unicode(length=255), nullable=True), - sa.Column('city', sa.Unicode(length=255), nullable=True), - sa.Column('state', sa.Unicode(length=255), nullable=True), - sa.Column('country', sa.Unicode(length=255), nullable=True), - sa.Column('latitude', sa.Numeric(precision=18, scale=16), nullable=True), - sa.Column('longitude', sa.Numeric(precision=19, scale=16), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "location", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("street", sa.Unicode(length=255), nullable=True), + sa.Column("postalCode", sa.Unicode(length=255), nullable=True), + sa.Column("city", sa.Unicode(length=255), nullable=True), + sa.Column("state", sa.Unicode(length=255), nullable=True), + sa.Column("country", sa.Unicode(length=255), nullable=True), + sa.Column("latitude", sa.Numeric(precision=18, scale=16), nullable=True), + sa.Column("longitude", sa.Numeric(precision=19, scale=16), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('roles_users', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('role_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['role_id'], ['role.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "roles_users", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("role_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["role_id"], + ["role.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('adminunitmember', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('admin_unit_id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "adminunitmember", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("admin_unit_id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('eventsuggestion', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('admin_unit_id', sa.Integer(), nullable=False), - sa.Column('host_name', sa.Unicode(length=255), nullable=False), - sa.Column('event_name', sa.Unicode(length=255), nullable=False), - sa.Column('description', sa.UnicodeText(), nullable=False), - sa.Column('place_name', sa.Unicode(length=255), nullable=False), - sa.Column('place_street', sa.Unicode(length=255), nullable=True), - sa.Column('place_postalCode', sa.Unicode(length=255), nullable=False), - sa.Column('place_city', sa.Unicode(length=255), nullable=False), - sa.Column('contact_name', sa.Unicode(length=255), nullable=False), - sa.Column('contact_email', sa.Unicode(length=255), nullable=False), - sa.Column('external_link', sa.String(length=255), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventsuggestion", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("admin_unit_id", sa.Integer(), nullable=False), + sa.Column("host_name", sa.Unicode(length=255), nullable=False), + sa.Column("event_name", sa.Unicode(length=255), nullable=False), + sa.Column("description", sa.UnicodeText(), nullable=False), + sa.Column("place_name", sa.Unicode(length=255), nullable=False), + sa.Column("place_street", sa.Unicode(length=255), nullable=True), + sa.Column("place_postalCode", sa.Unicode(length=255), nullable=False), + sa.Column("place_city", sa.Unicode(length=255), nullable=False), + sa.Column("contact_name", sa.Unicode(length=255), nullable=False), + sa.Column("contact_email", sa.Unicode(length=255), nullable=False), + sa.Column("external_link", sa.String(length=255), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('organization', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=True), - sa.Column('legal_name', sa.Unicode(length=255), nullable=True), - sa.Column('location_id', sa.Integer(), nullable=True), - sa.Column('logo_id', sa.Integer(), nullable=True), - sa.Column('url', sa.String(length=255), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['location_id'], ['location.id'], ), - sa.ForeignKeyConstraint(['logo_id'], ['image.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "organization", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=True), + sa.Column("legal_name", sa.Unicode(length=255), nullable=True), + sa.Column("location_id", sa.Integer(), nullable=True), + sa.Column("logo_id", sa.Integer(), nullable=True), + sa.Column("url", sa.String(length=255), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["location_id"], + ["location.id"], + ), + sa.ForeignKeyConstraint( + ["logo_id"], + ["image.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('place', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=False), - sa.Column('location_id', sa.Integer(), nullable=True), - sa.Column('photo_id', sa.Integer(), nullable=True), - sa.Column('url', sa.String(length=255), nullable=True), - sa.Column('description', sa.UnicodeText(), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['location_id'], ['location.id'], ), - sa.ForeignKeyConstraint(['photo_id'], ['image.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "place", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=False), + sa.Column("location_id", sa.Integer(), nullable=True), + sa.Column("photo_id", sa.Integer(), nullable=True), + sa.Column("url", sa.String(length=255), nullable=True), + sa.Column("description", sa.UnicodeText(), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["location_id"], + ["location.id"], + ), + sa.ForeignKeyConstraint( + ["photo_id"], + ["image.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('actor', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('organization_id', sa.Integer(), nullable=True), - sa.Column('admin_unit_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('user_id', 'organization_id', 'admin_unit_id') + op.create_table( + "actor", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("organization_id", sa.Integer(), nullable=True), + sa.Column("admin_unit_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["organization_id"], + ["organization.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("user_id", "organization_id", "admin_unit_id"), ) - op.create_table('adminunitmemberroles_members', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('member_id', sa.Integer(), nullable=True), - sa.Column('role_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['member_id'], ['adminunitmember.id'], ), - sa.ForeignKeyConstraint(['role_id'], ['adminunitmemberrole.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "adminunitmemberroles_members", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("member_id", sa.Integer(), nullable=True), + sa.Column("role_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["member_id"], + ["adminunitmember.id"], + ), + sa.ForeignKeyConstraint( + ["role_id"], + ["adminunitmemberrole.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('adminunitorg', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('admin_unit_id', sa.Integer(), nullable=False), - sa.Column('organization_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "adminunitorg", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("admin_unit_id", sa.Integer(), nullable=False), + sa.Column("organization_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["organization_id"], + ["organization.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('eventsuggestiondate', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('event_suggestion_id', sa.Integer(), nullable=False), - sa.Column('start', sa.DateTime(timezone=True), nullable=False), - sa.ForeignKeyConstraint(['event_suggestion_id'], ['eventsuggestion.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventsuggestiondate", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("event_suggestion_id", sa.Integer(), nullable=False), + sa.Column("start", sa.DateTime(timezone=True), nullable=False), + sa.ForeignKeyConstraint( + ["event_suggestion_id"], + ["eventsuggestion.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('org_or_adminunit', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('organization_id', sa.Integer(), nullable=True), - sa.Column('admin_unit_id', sa.Integer(), nullable=True), - sa.CheckConstraint('NOT(organization_id IS NULL AND admin_unit_id IS NULL)'), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('organization_id', 'admin_unit_id') + op.create_table( + "org_or_adminunit", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("organization_id", sa.Integer(), nullable=True), + sa.Column("admin_unit_id", sa.Integer(), nullable=True), + sa.CheckConstraint("NOT(organization_id IS NULL AND admin_unit_id IS NULL)"), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["organization_id"], + ["organization.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("organization_id", "admin_unit_id"), ) - op.create_table('orgmember', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('organization_id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "orgmember", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("organization_id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["organization_id"], + ["organization.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('adminunitorgroles_organizations', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('admin_unit_org_id', sa.Integer(), nullable=True), - sa.Column('role_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['admin_unit_org_id'], ['adminunitorg.id'], ), - sa.ForeignKeyConstraint(['role_id'], ['adminunitorgrole.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "adminunitorgroles_organizations", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("admin_unit_org_id", sa.Integer(), nullable=True), + sa.Column("role_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_org_id"], + ["adminunitorg.id"], + ), + sa.ForeignKeyConstraint( + ["role_id"], + ["adminunitorgrole.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('event', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('admin_unit_id', sa.Integer(), nullable=False), - sa.Column('host_id', sa.Integer(), nullable=False), - sa.Column('place_id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=False), - sa.Column('description', sa.UnicodeText(), nullable=False), - sa.Column('external_link', sa.String(length=255), nullable=True), - sa.Column('ticket_link', sa.String(length=255), nullable=True), - sa.Column('verified', sa.Boolean(), nullable=True), - sa.Column('photo_id', sa.Integer(), nullable=True), - sa.Column('category_id', sa.Integer(), nullable=False), - sa.Column('recurrence_rule', sa.UnicodeText(), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ), - sa.ForeignKeyConstraint(['category_id'], ['eventcategory.id'], ), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['host_id'], ['org_or_adminunit.id'], ), - sa.ForeignKeyConstraint(['photo_id'], ['image.id'], ), - sa.ForeignKeyConstraint(['place_id'], ['place.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "event", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("admin_unit_id", sa.Integer(), nullable=False), + sa.Column("host_id", sa.Integer(), nullable=False), + sa.Column("place_id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=False), + sa.Column("description", sa.UnicodeText(), nullable=False), + sa.Column("external_link", sa.String(length=255), nullable=True), + sa.Column("ticket_link", sa.String(length=255), nullable=True), + sa.Column("verified", sa.Boolean(), nullable=True), + sa.Column("photo_id", sa.Integer(), nullable=True), + sa.Column("category_id", sa.Integer(), nullable=False), + sa.Column("recurrence_rule", sa.UnicodeText(), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["admin_unit_id"], + ["adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["category_id"], + ["eventcategory.id"], + ), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["host_id"], + ["org_or_adminunit.id"], + ), + sa.ForeignKeyConstraint( + ["photo_id"], + ["image.id"], + ), + sa.ForeignKeyConstraint( + ["place_id"], + ["place.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('orgmemberroles_members', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('member_id', sa.Integer(), nullable=True), - sa.Column('role_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['member_id'], ['orgmember.id'], ), - sa.ForeignKeyConstraint(['role_id'], ['orgmemberrole.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "orgmemberroles_members", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("member_id", sa.Integer(), nullable=True), + sa.Column("role_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["member_id"], + ["orgmember.id"], + ), + sa.ForeignKeyConstraint( + ["role_id"], + ["orgmemberrole.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('eventdate', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('event_id', sa.Integer(), nullable=False), - sa.Column('start', sa.DateTime(timezone=True), nullable=False), - sa.ForeignKeyConstraint(['event_id'], ['event.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventdate", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("event_id", sa.Integer(), nullable=False), + sa.Column("start", sa.DateTime(timezone=True), nullable=False), + sa.ForeignKeyConstraint( + ["event_id"], + ["event.id"], + ), + sa.PrimaryKeyConstraint("id"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('eventdate') - op.drop_table('orgmemberroles_members') - op.drop_table('event') - op.drop_table('adminunitorgroles_organizations') - op.drop_table('orgmember') - op.drop_table('org_or_adminunit') - op.drop_table('eventsuggestiondate') - op.drop_table('adminunitorg') - op.drop_table('adminunitmemberroles_members') - op.drop_table('actor') - op.drop_table('place') - op.drop_table('organization') - op.drop_table('eventsuggestion') - op.drop_table('adminunitmember') - op.drop_table('roles_users') - op.drop_table('location') - op.drop_table('image') - op.drop_table('adminunit') - op.drop_table('user') - op.drop_table('role') - op.drop_table('orgmemberrole') - op.drop_table('eventcategory') - op.drop_table('adminunitorgrole') - op.drop_table('adminunitmemberrole') + op.drop_table("eventdate") + op.drop_table("orgmemberroles_members") + op.drop_table("event") + op.drop_table("adminunitorgroles_organizations") + op.drop_table("orgmember") + op.drop_table("org_or_adminunit") + op.drop_table("eventsuggestiondate") + op.drop_table("adminunitorg") + op.drop_table("adminunitmemberroles_members") + op.drop_table("actor") + op.drop_table("place") + op.drop_table("organization") + op.drop_table("eventsuggestion") + op.drop_table("adminunitmember") + op.drop_table("roles_users") + op.drop_table("location") + op.drop_table("image") + op.drop_table("adminunit") + op.drop_table("user") + op.drop_table("role") + op.drop_table("orgmemberrole") + op.drop_table("eventcategory") + op.drop_table("adminunitorgrole") + op.drop_table("adminunitmemberrole") # ### end Alembic commands ### diff --git a/migrations/versions/cce1284874fa_.py b/migrations/versions/cce1284874fa_.py index 9d91018..b4b6a5d 100644 --- a/migrations/versions/cce1284874fa_.py +++ b/migrations/versions/cce1284874fa_.py @@ -12,21 +12,25 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'cce1284874fa' -down_revision = 'b128cc637447' +revision = "cce1284874fa" +down_revision = "b128cc637447" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('adminunit', sa.Column('short_name', sa.Unicode(length=100), nullable=True)) - op.add_column('organization', sa.Column('short_name', sa.Unicode(length=100), nullable=True)) + op.add_column( + "adminunit", sa.Column("short_name", sa.Unicode(length=100), nullable=True) + ) + op.add_column( + "organization", sa.Column("short_name", sa.Unicode(length=100), nullable=True) + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('organization', 'short_name') - op.drop_column('adminunit', 'short_name') + op.drop_column("organization", "short_name") + op.drop_column("adminunit", "short_name") # ### end Alembic commands ### diff --git a/migrations/versions/da63ba1d58b1_.py b/migrations/versions/da63ba1d58b1_.py index 2f8b885..c9c816e 100644 --- a/migrations/versions/da63ba1d58b1_.py +++ b/migrations/versions/da63ba1d58b1_.py @@ -12,29 +12,40 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'da63ba1d58b1' -down_revision = '091deace5f08' +revision = "da63ba1d58b1" +down_revision = "091deace5f08" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - #op.drop_table('spatial_ref_sys') - op.add_column('image', sa.Column('copyright_text', sa.Unicode(length=255), nullable=True)) + # op.drop_table('spatial_ref_sys') + op.add_column( + "image", sa.Column("copyright_text", sa.Unicode(length=255), nullable=True) + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('image', 'copyright_text') - op.create_table('spatial_ref_sys', - sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), - sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), - sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), - sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + op.drop_column("image", "copyright_text") + op.create_table( + "spatial_ref_sys", + sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column( + "auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True + ), + sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column( + "srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.Column( + "proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True + ), + sa.CheckConstraint( + "(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check" + ), + sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"), ) # ### end Alembic commands ### diff --git a/migrations/versions/dcd0b71650b0_.py b/migrations/versions/dcd0b71650b0_.py index fd3d5c7..811c074 100644 --- a/migrations/versions/dcd0b71650b0_.py +++ b/migrations/versions/dcd0b71650b0_.py @@ -12,25 +12,27 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'dcd0b71650b0' -down_revision = '699c4f6a7fe8' +revision = "dcd0b71650b0" +down_revision = "699c4f6a7fe8" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('eventorganizer', sa.Column('location_id', sa.Integer(), nullable=True)) - op.add_column('eventorganizer', sa.Column('logo_id', sa.Integer(), nullable=True)) - op.create_foreign_key(None, 'eventorganizer', 'image', ['logo_id'], ['id']) - op.create_foreign_key(None, 'eventorganizer', 'location', ['location_id'], ['id']) + op.add_column( + "eventorganizer", sa.Column("location_id", sa.Integer(), nullable=True) + ) + op.add_column("eventorganizer", sa.Column("logo_id", sa.Integer(), nullable=True)) + op.create_foreign_key(None, "eventorganizer", "image", ["logo_id"], ["id"]) + op.create_foreign_key(None, "eventorganizer", "location", ["location_id"], ["id"]) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'eventorganizer', type_='foreignkey') - op.drop_constraint(None, 'eventorganizer', type_='foreignkey') - op.drop_column('eventorganizer', 'logo_id') - op.drop_column('eventorganizer', 'location_id') + op.drop_constraint(None, "eventorganizer", type_="foreignkey") + op.drop_constraint(None, "eventorganizer", type_="foreignkey") + op.drop_column("eventorganizer", "logo_id") + op.drop_column("eventorganizer", "location_id") # ### end Alembic commands ### diff --git a/migrations/versions/ed6bb2084bbd_.py b/migrations/versions/ed6bb2084bbd_.py index cdcb04e..c9b639e 100644 --- a/migrations/versions/ed6bb2084bbd_.py +++ b/migrations/versions/ed6bb2084bbd_.py @@ -7,26 +7,29 @@ Create Date: 2020-07-08 08:53:44.373606 """ from alembic import op import sqlalchemy as sa -import sqlalchemy_utils -from project import dbtypes # revision identifiers, used by Alembic. -revision = 'ed6bb2084bbd' -down_revision = 'f1bc3fa623c7' +revision = "ed6bb2084bbd" +down_revision = "f1bc3fa623c7" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('event', sa.Column('previous_start_date', sa.DateTime(timezone=True), nullable=True)) - op.add_column('eventdate', sa.Column('end', sa.DateTime(timezone=True), nullable=True)) + op.add_column( + "event", + sa.Column("previous_start_date", sa.DateTime(timezone=True), nullable=True), + ) + op.add_column( + "eventdate", sa.Column("end", sa.DateTime(timezone=True), nullable=True) + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('eventdate', 'end') - op.drop_column('event', 'previous_start_date') + op.drop_column("eventdate", "end") + op.drop_column("event", "previous_start_date") # ### end Alembic commands ### diff --git a/migrations/versions/f1bc3fa623c7_.py b/migrations/versions/f1bc3fa623c7_.py index 11e5602..4a609c6 100644 --- a/migrations/versions/f1bc3fa623c7_.py +++ b/migrations/versions/f1bc3fa623c7_.py @@ -7,38 +7,53 @@ Create Date: 2020-07-07 15:49:58.653888 """ from alembic import op import sqlalchemy as sa -import sqlalchemy_utils from project import dbtypes from project.models import EventTargetGroupOrigin, EventAttendanceMode, EventStatus # revision identifiers, used by Alembic. -revision = 'f1bc3fa623c7' -down_revision = '75c07cb9cfe3' +revision = "f1bc3fa623c7" +down_revision = "75c07cb9cfe3" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('event', sa.Column('accessible_for_free', sa.Boolean(), nullable=True)) - op.add_column('event', sa.Column('age_from', sa.Integer(), nullable=True)) - op.add_column('event', sa.Column('age_to', sa.Integer(), nullable=True)) - op.add_column('event', sa.Column('attendance_mode', dbtypes.IntegerEnum(EventAttendanceMode), nullable=True)) - op.add_column('event', sa.Column('kid_friendly', sa.Boolean(), nullable=True)) - op.add_column('event', sa.Column('status', dbtypes.IntegerEnum(EventStatus), nullable=True)) - op.add_column('event', sa.Column('tags', sa.UnicodeText(), nullable=True)) - op.add_column('event', sa.Column('target_group_origin', dbtypes.IntegerEnum(EventTargetGroupOrigin), nullable=True)) + op.add_column( + "event", sa.Column("accessible_for_free", sa.Boolean(), nullable=True) + ) + op.add_column("event", sa.Column("age_from", sa.Integer(), nullable=True)) + op.add_column("event", sa.Column("age_to", sa.Integer(), nullable=True)) + op.add_column( + "event", + sa.Column( + "attendance_mode", dbtypes.IntegerEnum(EventAttendanceMode), nullable=True + ), + ) + op.add_column("event", sa.Column("kid_friendly", sa.Boolean(), nullable=True)) + op.add_column( + "event", sa.Column("status", dbtypes.IntegerEnum(EventStatus), nullable=True) + ) + op.add_column("event", sa.Column("tags", sa.UnicodeText(), nullable=True)) + op.add_column( + "event", + sa.Column( + "target_group_origin", + dbtypes.IntegerEnum(EventTargetGroupOrigin), + nullable=True, + ), + ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('event', 'target_group_origin') - op.drop_column('event', 'tags') - op.drop_column('event', 'status') - op.drop_column('event', 'kid_friendly') - op.drop_column('event', 'attendance_mode') - op.drop_column('event', 'age_to') - op.drop_column('event', 'age_from') - op.drop_column('event', 'accessible_for_free') + op.drop_column("event", "target_group_origin") + op.drop_column("event", "tags") + op.drop_column("event", "status") + op.drop_column("event", "kid_friendly") + op.drop_column("event", "attendance_mode") + op.drop_column("event", "age_to") + op.drop_column("event", "age_from") + op.drop_column("event", "accessible_for_free") # ### end Alembic commands ### diff --git a/migrations/versions/f71c86333bfb_.py b/migrations/versions/f71c86333bfb_.py index 2950384..e5470e9 100644 --- a/migrations/versions/f71c86333bfb_.py +++ b/migrations/versions/f71c86333bfb_.py @@ -12,23 +12,29 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'f71c86333bfb' -down_revision = '4e913af88c33' +revision = "f71c86333bfb" +down_revision = "4e913af88c33" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('analytics', sa.Column('value1', sa.Unicode(length=255), nullable=True)) - op.add_column('analytics', sa.Column('value2', sa.Unicode(length=255), nullable=True)) - op.drop_column('analytics', 'value') + op.add_column( + "analytics", sa.Column("value1", sa.Unicode(length=255), nullable=True) + ) + op.add_column( + "analytics", sa.Column("value2", sa.Unicode(length=255), nullable=True) + ) + op.drop_column("analytics", "value") # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.add_column('analytics', sa.Column('value', sa.TEXT(), autoincrement=False, nullable=True)) - op.drop_column('analytics', 'value2') - op.drop_column('analytics', 'value1') + op.add_column( + "analytics", sa.Column("value", sa.TEXT(), autoincrement=False, nullable=True) + ) + op.drop_column("analytics", "value2") + op.drop_column("analytics", "value1") # ### end Alembic commands ### diff --git a/migrations/versions/fd7794ece0b3_.py b/migrations/versions/fd7794ece0b3_.py index 37281e5..97be003 100644 --- a/migrations/versions/fd7794ece0b3_.py +++ b/migrations/versions/fd7794ece0b3_.py @@ -12,36 +12,46 @@ from project import dbtypes # revision identifiers, used by Alembic. -revision = 'fd7794ece0b3' -down_revision = '975c22ae802b' +revision = "fd7794ece0b3" +down_revision = "975c22ae802b" branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('eventplace', - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.Unicode(length=255), nullable=False), - sa.Column('location_id', sa.Integer(), nullable=True), - sa.Column('photo_id', sa.Integer(), nullable=True), - sa.Column('url', sa.String(length=255), nullable=True), - sa.Column('description', sa.UnicodeText(), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['location_id'], ['location.id'], ), - sa.ForeignKeyConstraint(['photo_id'], ['image.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "eventplace", + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.Unicode(length=255), nullable=False), + sa.Column("location_id", sa.Integer(), nullable=True), + sa.Column("photo_id", sa.Integer(), nullable=True), + sa.Column("url", sa.String(length=255), nullable=True), + sa.Column("description", sa.UnicodeText(), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["location_id"], + ["location.id"], + ), + sa.ForeignKeyConstraint( + ["photo_id"], + ["image.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.add_column('event', sa.Column('event_place_id', sa.Integer(), nullable=True)) - op.create_foreign_key(None, 'event', 'place', ['event_place_id'], ['id']) + op.add_column("event", sa.Column("event_place_id", sa.Integer(), nullable=True)) + op.create_foreign_key(None, "event", "place", ["event_place_id"], ["id"]) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'event', type_='foreignkey') - op.drop_column('event', 'event_place_id') - op.drop_table('eventplace') + op.drop_constraint(None, "event", type_="foreignkey") + op.drop_column("event", "event_place_id") + op.drop_table("eventplace") # ### end Alembic commands ### diff --git a/project/__init__.py b/project/__init__.py index 1fb0caa..6f4026f 100644 --- a/project/__init__.py +++ b/project/__init__.py @@ -1,46 +1,45 @@ import os -from base64 import b64decode -from flask import jsonify, Flask, render_template, request, url_for, redirect, abort, flash, current_app +from flask import Flask from flask_sqlalchemy import SQLAlchemy -from sqlalchemy.orm import joinedload -from sqlalchemy.sql import asc, func -from sqlalchemy import and_, or_, not_, event -from flask_security import Security, current_user, auth_required, roles_required, SQLAlchemySessionUserDatastore -from flask_security.utils import FsPermNeed -from flask_babelex import Babel, gettext, lazy_gettext, format_datetime, to_user_timezone -from flask_principal import Permission +from flask_security import ( + Security, + SQLAlchemySessionUserDatastore, +) +from flask_babelex import Babel from flask_cors import CORS -import pytz -import json from flask_qrcode import QRcode -from flask_mail import Mail, Message, email_dispatched +from flask_mail import Mail, email_dispatched # Create app app = Flask(__name__) -app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL'] -app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -app.config['SECURITY_CONFIRMABLE'] = False -app.config['SECURITY_TRACKABLE'] = True -app.config['SECURITY_REGISTERABLE'] = True -app.config['SECURITY_SEND_REGISTER_EMAIL'] = False -app.config['SECURITY_RECOVERABLE'] = True -app.config['SECURITY_CHANGEABLE'] = True -app.config['SECURITY_EMAIL_SENDER'] = os.getenv("MAIL_DEFAULT_SENDER") -app.config['LANGUAGES'] = ['en', 'de'] -app.config['GOOGLE_OAUTH_CLIENT_ID'] = os.getenv('GOOGLE_OAUTH_CLIENT_ID') -app.config['GOOGLE_OAUTH_CLIENT_SECRET'] = os.getenv('GOOGLE_OAUTH_CLIENT_SECRET') -app.config['OAUTHLIB_INSECURE_TRANSPORT'] = True -app.config['OAUTHLIB_RELAX_TOKEN_SCOPE'] = True +app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["DATABASE_URL"] +app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False +app.config["SECURITY_CONFIRMABLE"] = False +app.config["SECURITY_TRACKABLE"] = True +app.config["SECURITY_REGISTERABLE"] = True +app.config["SECURITY_SEND_REGISTER_EMAIL"] = False +app.config["SECURITY_RECOVERABLE"] = True +app.config["SECURITY_CHANGEABLE"] = True +app.config["SECURITY_EMAIL_SENDER"] = os.getenv("MAIL_DEFAULT_SENDER") +app.config["LANGUAGES"] = ["en", "de"] +app.config["GOOGLE_OAUTH_CLIENT_ID"] = os.getenv("GOOGLE_OAUTH_CLIENT_ID") +app.config["GOOGLE_OAUTH_CLIENT_SECRET"] = os.getenv("GOOGLE_OAUTH_CLIENT_SECRET") +app.config["OAUTHLIB_INSECURE_TRANSPORT"] = True +app.config["OAUTHLIB_RELAX_TOKEN_SCOPE"] = True # Generate a nice key using secrets.token_urlsafe() -app.config['SECRET_KEY'] = os.environ.get("SECRET_KEY", 'pf9Wkove4IKEAXvy-cQkeDPhv9Cb3Ag-wyJILbq_dFw') +app.config["SECRET_KEY"] = os.environ.get( + "SECRET_KEY", "pf9Wkove4IKEAXvy-cQkeDPhv9Cb3Ag-wyJILbq_dFw" +) # Bcrypt is set as default SECURITY_PASSWORD_HASH, which requires a salt # Generate a good salt using: secrets.SystemRandom().getrandbits(128) -app.config['SECURITY_PASSWORD_SALT'] = os.environ.get("SECURITY_PASSWORD_SALT", '146585145368132386173505678016728509634') +app.config["SECURITY_PASSWORD_SALT"] = os.environ.get( + "SECURITY_PASSWORD_SALT", "146585145368132386173505678016728509634" +) # i18n -app.config['BABEL_DEFAULT_LOCALE'] = 'de' -app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Berlin' +app.config["BABEL_DEFAULT_LOCALE"] = "de" +app.config["BABEL_DEFAULT_TIMEZONE"] = "Europe/Berlin" babel = Babel(app) # cors @@ -50,24 +49,26 @@ cors = CORS(app, resources={r"/api/*": {"origins": "*"}}) mail_server = os.getenv("MAIL_SERVER") if mail_server is None: - app.config['MAIL_SUPPRESS_SEND'] = True - app.config['MAIL_DEFAULT_SENDER'] = 'test@oveda.de' + app.config["MAIL_SUPPRESS_SEND"] = True + app.config["MAIL_DEFAULT_SENDER"] = "test@oveda.de" else: - app.config['MAIL_SUPPRESS_SEND'] = False - app.config['MAIL_SERVER'] = mail_server - app.config['MAIL_PORT'] = os.getenv("MAIL_PORT") - app.config['MAIL_USE_TLS'] = os.getenv("MAIL_USE_TLS", True) - app.config['MAIL_USE_SSL'] = os.getenv("MAIL_USE_SSL", False) - app.config['MAIL_USERNAME'] = os.getenv("MAIL_USERNAME") - app.config['MAIL_PASSWORD'] = os.getenv("MAIL_PASSWORD") - app.config['MAIL_DEFAULT_SENDER'] = os.getenv("MAIL_DEFAULT_SENDER") + app.config["MAIL_SUPPRESS_SEND"] = False + app.config["MAIL_SERVER"] = mail_server + app.config["MAIL_PORT"] = os.getenv("MAIL_PORT") + app.config["MAIL_USE_TLS"] = os.getenv("MAIL_USE_TLS", True) + app.config["MAIL_USE_SSL"] = os.getenv("MAIL_USE_SSL", False) + app.config["MAIL_USERNAME"] = os.getenv("MAIL_USERNAME") + app.config["MAIL_PASSWORD"] = os.getenv("MAIL_PASSWORD") + app.config["MAIL_DEFAULT_SENDER"] = os.getenv("MAIL_DEFAULT_SENDER") mail = Mail(app) -if app.config['MAIL_SUPPRESS_SEND']: +if app.config["MAIL_SUPPRESS_SEND"]: + def log_message(message, app): print(message.subject) print(message.body) + email_dispatched.connect(log_message) # Create db @@ -78,20 +79,23 @@ QRcode(app) # JSON from project.jsonld import DateTimeEncoder + app.json_encoder = DateTimeEncoder # Setup Flask-Security from project.models import User, Role + user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) security = Security(app, user_datastore) # OAuth from project.oauth import blueprint + app.register_blueprint(blueprint, url_prefix="/login") -from project.i10n import * -from project.jinja_filters import * -from project.init_data import * +from project import i10n +from project import jinja_filters +from project import init_data # Routes from project.views import ( @@ -113,8 +117,8 @@ from project.views import ( reference_request_review, root, user, - widget + widget, ) -if __name__ == '__main__': - app.run() \ No newline at end of file +if __name__ == "__main__": + app.run() diff --git a/project/access.py b/project/access.py index d860af8..b1f6fce 100644 --- a/project/access.py +++ b/project/access.py @@ -4,23 +4,29 @@ from flask_security.utils import FsPermNeed from flask_principal import Permission from project.models import AdminUnitMember, AdminUnit + def has_current_user_permission(permission): user_perm = Permission(FsPermNeed(permission)) return user_perm.can() + def has_admin_unit_member_permission(admin_unit_member, permission): for role in admin_unit_member.roles: if permission in role.get_permissions(): return True return False + def has_current_user_member_permission_for_admin_unit(admin_unit_id, permission): - admin_unit_member = AdminUnitMember.query.filter_by(admin_unit_id=admin_unit_id, user_id=current_user.id).first() + admin_unit_member = AdminUnitMember.query.filter_by( + admin_unit_id=admin_unit_id, user_id=current_user.id + ).first() if admin_unit_member is not None: if has_admin_unit_member_permission(admin_unit_member, permission): return True return False + def has_current_user_permission_for_admin_unit(admin_unit, permission): if not current_user.is_authenticated: return False @@ -33,40 +39,54 @@ def has_current_user_permission_for_admin_unit(admin_unit, permission): return False + def has_access(admin_unit, permission): return has_current_user_permission_for_admin_unit(admin_unit, permission) + def access_or_401(admin_unit, permission): if not has_access(admin_unit, permission): abort(401) + def can_list_admin_unit_members(admin_unit): - return has_current_user_permission_for_admin_unit(admin_unit, 'admin_unit.members:read') + return has_current_user_permission_for_admin_unit( + admin_unit, "admin_unit.members:read" + ) + def can_create_event(admin_unit): - return has_current_user_permission_for_admin_unit(admin_unit, 'event:create') + return has_current_user_permission_for_admin_unit(admin_unit, "event:create") + def can_update_event(event): - return has_current_user_permission_for_admin_unit(event.admin_unit, 'event:update') + return has_current_user_permission_for_admin_unit(event.admin_unit, "event:update") + def can_delete_event(event): - return has_current_user_permission_for_admin_unit(event.admin_unit, 'event:delete') + return has_current_user_permission_for_admin_unit(event.admin_unit, "event:delete") + def can_reference_event(event): return len(get_admin_units_for_event_reference(event)) > 0 + def can_update_organizer(organizer): return get_admin_unit_for_manage(organizer.admin_unit_id) is not None + def can_create_admin_unit(): return current_user.is_authenticated + def can_verify_event_for_admin_unit(admin_unit): - return has_current_user_permission_for_admin_unit(admin_unit, 'event:verify') + return has_current_user_permission_for_admin_unit(admin_unit, "event:verify") + def can_verify_event(event): return can_verify_event_for_admin_unit(event.admin_unit) + def get_admin_units_with_current_user_permission(permission): result = list() @@ -77,41 +97,48 @@ def get_admin_units_with_current_user_permission(permission): return result + def get_admin_units_for_event_reference(event): result = list() - admin_units = get_admin_units_with_current_user_permission('event:reference') + admin_units = get_admin_units_with_current_user_permission("event:reference") for admin_unit in admin_units: if admin_unit.id != event.admin_unit_id: result.append(admin_unit) return result + def admin_units_the_current_user_is_member_of(): result = list() if current_user.is_authenticated: - admin_unit_members = AdminUnitMember.query.filter_by(user_id=current_user.id).all() + admin_unit_members = AdminUnitMember.query.filter_by( + user_id=current_user.id + ).all() for admin_unit_member in admin_unit_members: result.append(admin_unit_member.adminunit) return result + def get_admin_units_for_manage(): # Global admin - if current_user.has_role('admin'): + if current_user.has_role("admin"): return AdminUnit.query.all() return admin_units_the_current_user_is_member_of() + def get_admin_unit_for_manage(admin_unit_id): admin_units = get_admin_units_for_manage() return next((au for au in admin_units if au.id == admin_unit_id), None) + def get_admin_unit_for_manage_or_404(admin_unit_id): admin_unit = get_admin_unit_for_manage(admin_unit_id) if not admin_unit: abort(404) - return admin_unit \ No newline at end of file + return admin_unit diff --git a/project/dateutils.py b/project/dateutils.py index 404d78c..58d6013 100644 --- a/project/dateutils.py +++ b/project/dateutils.py @@ -1,41 +1,58 @@ import pytz -from dateutil import rrule -from dateutil.rrule import rrulestr, rruleset, rrule +from dateutil.rrule import rrulestr from datetime import datetime from dateutil.relativedelta import relativedelta -berlin_tz = pytz.timezone('Europe/Berlin') +berlin_tz = pytz.timezone("Europe/Berlin") now = datetime.now(tz=berlin_tz) today = datetime(now.year, now.month, now.day, tzinfo=now.tzinfo) -def create_berlin_date(year, month, day, hour, minute = 0): + +def create_berlin_date(year, month, day, hour, minute=0): return berlin_tz.localize(datetime(year, month, day, hour=hour, minute=minute)) + def date_add_time(date, hour=0, minute=0, second=0, tzinfo=None): - return datetime(date.year, date.month, date.day, hour=hour, minute=minute, second=second, tzinfo=tzinfo) + return datetime( + date.year, + date.month, + date.day, + hour=hour, + minute=minute, + second=second, + tzinfo=tzinfo, + ) + def date_set_end_of_day(date): return date_add_time(date, hour=23, minute=59, second=59) + def form_input_to_date(date_str, hour=0, minute=0, second=0): date = datetime.strptime(date_str, "%Y-%m-%d") date_time = date_add_time(date, hour=hour, minute=minute, second=second) return berlin_tz.localize(date_time) + def form_input_from_date(date): return date.strftime("%Y-%m-%d") + def dates_from_recurrence_rule(start, recurrence_rule): result = list() - adv_recurrence_rule = recurrence_rule.replace('T000000', 'T235959') + adv_recurrence_rule = recurrence_rule.replace("T000000", "T235959") start_wo_tz = start.replace(tzinfo=None) rule_set = rrulestr(adv_recurrence_rule, forceset=True, dtstart=start_wo_tz) start_date = start_wo_tz end_date = start_date + relativedelta(years=1) - start_date_begin_of_day = datetime(start_date.year, start_date.month, start_date.day) - end_date_end_of_day = datetime(end_date.year, end_date.month, end_date.day, hour=23, minute=59, second=59) + start_date_begin_of_day = datetime( + start_date.year, start_date.month, start_date.day + ) + end_date_end_of_day = datetime( + end_date.year, end_date.month, end_date.day, hour=23, minute=59, second=59 + ) for rule_date in rule_set.between(start_date_begin_of_day, end_date_end_of_day): rule_data_w_tz = berlin_tz.localize(rule_date) @@ -43,7 +60,9 @@ def dates_from_recurrence_rule(start, recurrence_rule): return result -BATCH_DELTA = 3 # How many batches to show before + after current batch + +BATCH_DELTA = 3 # How many batches to show before + after current batch + def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size): # TODO: Return error on failure @@ -53,9 +72,9 @@ def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size) iterator = iter(rule) cur_batch = start // batch_size - start = cur_batch * batch_size # Avoid stupid start-values + start = cur_batch * batch_size # Avoid stupid start-values - if hasattr(rule, '_exdate'): + if hasattr(rule, "_exdate"): exdates = sorted(rule._exdate) else: exdates = [] @@ -79,13 +98,17 @@ def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size) else: # include them exdate = exdates.pop(0) - occurrences.append({'date': exdate.strftime('%Y%m%dT%H%M%S'), - 'formattedDate': exdate.strftime(date_format), - 'type': 'exdate',}) + occurrences.append( + { + "date": exdate.strftime("%Y%m%dT%H%M%S"), + "formattedDate": exdate.strftime(date_format), + "type": "exdate", + } + ) i += 1 if i >= batch_size + start: - break # We are done! + break # We are done! i += 1 if i <= start: @@ -93,24 +116,32 @@ def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size) continue # Add it to the results - if date in getattr(rule, '_rdate', []): - occurrence_type = 'rdate' + if date in getattr(rule, "_rdate", []): + occurrence_type = "rdate" elif date == start_date: - occurrence_type = 'start' + occurrence_type = "start" else: - occurrence_type = 'rrule' - occurrences.append({'date': date.strftime('%Y%m%dT%H%M%S'), - 'formattedDate': date.strftime(date_format), - 'type': occurrence_type,}) + occurrence_type = "rrule" + occurrences.append( + { + "date": date.strftime("%Y%m%dT%H%M%S"), + "formattedDate": date.strftime(date_format), + "type": occurrence_type, + } + ) while exdates: # There are exdates that are after the end of the recurrence. # Excluding the last dates make no sense, as you can change the # range instead, but we need to support it anyway. exdate = exdates.pop(0) - occurrences.append({'date': exdate.strftime('%Y%m%dT%H%M%S'), - 'formattedDate': exdate.strftime(date_format), - 'type': 'exdate',}) + occurrences.append( + { + "date": exdate.strftime("%Y%m%dT%H%M%S"), + "formattedDate": exdate.strftime(date_format), + "type": "exdate", + } + ) # Calculate no of occurrences, but only to a max of three times # the batch size. This will support infinite recurrence in a @@ -132,18 +163,21 @@ def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size) # Total number of occurrences: num_occurrences += batch_size + start - max_batch = (num_occurrences - 1)//batch_size + max_batch = (num_occurrences - 1) // batch_size if last_batch > max_batch: last_batch = max_batch first_batch = max(0, max_batch - (BATCH_DELTA * 2)) - batches = [((x * batch_size) + 1, (x + 1) * batch_size) for x in range(first_batch, last_batch + 1)] - batch_data = {'start': start, - 'end': num_occurrences, - 'batch_size': batch_size, - 'batches': batches, - 'currentBatch': cur_batch - first_batch, - } - - return {'occurrences': occurrences, 'batch': batch_data} + batches = [ + ((x * batch_size) + 1, (x + 1) * batch_size) + for x in range(first_batch, last_batch + 1) + ] + batch_data = { + "start": start, + "end": num_occurrences, + "batch_size": batch_size, + "batches": batches, + "currentBatch": cur_batch - first_batch, + } + return {"occurrences": occurrences, "batch": batch_data} diff --git a/project/dbtypes.py b/project/dbtypes.py index 536092c..311aa72 100644 --- a/project/dbtypes.py +++ b/project/dbtypes.py @@ -1,8 +1,10 @@ from sqlalchemy.types import TypeDecorator from sqlalchemy import Integer + class IntegerEnum(TypeDecorator): impl = Integer + def __init__(self, enumtype, *args, **kwargs): super().__init__(*args, **kwargs) self._enumtype = enumtype diff --git a/project/forms/admin_unit.py b/project/forms/admin_unit.py index e1d8903..7bcb205 100644 --- a/project/forms/admin_unit.py +++ b/project/forms/admin_unit.py @@ -1,49 +1,90 @@ from flask_babelex import lazy_gettext from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from wtforms import StringField, SubmitField, DecimalField, TextAreaField, FormField, SelectField +from wtforms import ( + StringField, + SubmitField, + DecimalField, + FormField, +) from wtforms.fields.html5 import EmailField, TelField, URLField from wtforms.validators import DataRequired, Optional, Regexp from wtforms.widgets.html5 import ColorInput -import decimal from project.models import Location, Image from project.forms.common import FileImageForm + class AdminUnitLocationForm(FlaskForm): - street = StringField(lazy_gettext('Street'), validators=[Optional()]) - postalCode = StringField(lazy_gettext('Postal code'), validators=[DataRequired()]) - city = StringField(lazy_gettext('City'), validators=[DataRequired()]) - state = StringField(lazy_gettext('State'), validators=[Optional()]) - latitude = DecimalField(lazy_gettext('Latitude'), places=16, validators=[Optional()]) - longitude = DecimalField(lazy_gettext('Longitude'), places=16, validators=[Optional()]) + street = StringField(lazy_gettext("Street"), validators=[Optional()]) + postalCode = StringField(lazy_gettext("Postal code"), validators=[DataRequired()]) + city = StringField(lazy_gettext("City"), validators=[DataRequired()]) + state = StringField(lazy_gettext("State"), validators=[Optional()]) + latitude = DecimalField( + lazy_gettext("Latitude"), places=16, validators=[Optional()] + ) + longitude = DecimalField( + lazy_gettext("Longitude"), places=16, validators=[Optional()] + ) + class BaseAdminUnitForm(FlaskForm): - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) - short_name = StringField(lazy_gettext('Short name'), description=lazy_gettext('The short name is used to create a unique identifier for your events'), validators=[DataRequired(), Regexp('^\w+$', message=lazy_gettext("Short name must contain only letters numbers or underscore"))]) - url = URLField(lazy_gettext('Link URL'), validators=[Optional()]) - email = EmailField(lazy_gettext('Email'), validators=[Optional()]) - phone = TelField(lazy_gettext('Phone'), validators=[Optional()]) - fax = TelField(lazy_gettext('Fax'), validators=[Optional()]) - logo = FormField(FileImageForm, lazy_gettext('Logo'), default=lambda: Image()) + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) + short_name = StringField( + lazy_gettext("Short name"), + description=lazy_gettext( + "The short name is used to create a unique identifier for your events" + ), + validators=[ + DataRequired(), + Regexp( + r"^\w+$", + message=lazy_gettext( + "Short name must contain only letters numbers or underscore" + ), + ), + ], + ) + url = URLField(lazy_gettext("Link URL"), validators=[Optional()]) + email = EmailField(lazy_gettext("Email"), validators=[Optional()]) + phone = TelField(lazy_gettext("Phone"), validators=[Optional()]) + fax = TelField(lazy_gettext("Fax"), validators=[Optional()]) + logo = FormField(FileImageForm, lazy_gettext("Logo"), default=lambda: Image()) location = FormField(AdminUnitLocationForm, default=lambda: Location()) def populate_obj(self, obj): for name, field in self._fields.items(): - if name == 'location' and not obj.location: + if name == "location" and not obj.location: obj.location = Location() - elif name == 'logo' and not obj.logo: + elif name == "logo" and not obj.logo: obj.logo = Image() field.populate_obj(obj, name) + class CreateAdminUnitForm(BaseAdminUnitForm): submit = SubmitField(lazy_gettext("Create admin unit")) + class UpdateAdminUnitForm(BaseAdminUnitForm): submit = SubmitField(lazy_gettext("Update settings")) + class UpdateAdminUnitWidgetForm(FlaskForm): - widget_font = StringField(lazy_gettext('Font'), validators=[Optional()]) - widget_background_color = StringField(lazy_gettext('Background Color'), default='#ffffff', widget=ColorInput(), validators=[Optional()]) - widget_primary_color = StringField(lazy_gettext('Primary Color'), default='#007bff', widget=ColorInput(), validators=[Optional()]) - widget_link_color = StringField(lazy_gettext('Link Color'), default='#007bff', widget=ColorInput(), validators=[Optional()]) - submit = SubmitField(lazy_gettext("Update settings")) \ No newline at end of file + widget_font = StringField(lazy_gettext("Font"), validators=[Optional()]) + widget_background_color = StringField( + lazy_gettext("Background Color"), + default="#ffffff", + widget=ColorInput(), + validators=[Optional()], + ) + widget_primary_color = StringField( + lazy_gettext("Primary Color"), + default="#007bff", + widget=ColorInput(), + validators=[Optional()], + ) + widget_link_color = StringField( + lazy_gettext("Link Color"), + default="#007bff", + widget=ColorInput(), + validators=[Optional()], + ) + submit = SubmitField(lazy_gettext("Update settings")) diff --git a/project/forms/admin_unit_member.py b/project/forms/admin_unit_member.py index e6a1a80..e13e7d8 100644 --- a/project/forms/admin_unit_member.py +++ b/project/forms/admin_unit_member.py @@ -1,31 +1,32 @@ from flask_babelex import lazy_gettext from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from wtforms import StringField, SubmitField, DecimalField, TextAreaField, FormField, SelectField -from wtforms.fields.html5 import EmailField, TelField -from wtforms.validators import DataRequired, Optional, Regexp -import decimal -from project.models import Location +from wtforms import SubmitField +from wtforms.fields.html5 import EmailField +from wtforms.validators import DataRequired from project.forms.widgets import MultiCheckboxField + class InviteAdminUnitMemberForm(FlaskForm): - email = EmailField(lazy_gettext('Email'), validators=[DataRequired()]) - roles = MultiCheckboxField(lazy_gettext('Roles')) + email = EmailField(lazy_gettext("Email"), validators=[DataRequired()]) + roles = MultiCheckboxField(lazy_gettext("Roles")) submit = SubmitField(lazy_gettext("Invite")) + class NegotiateAdminUnitMemberInvitationForm(FlaskForm): accept = SubmitField(lazy_gettext("Accept")) decline = SubmitField(lazy_gettext("Decline")) + class DeleteAdminUnitInvitationForm(FlaskForm): submit = SubmitField(lazy_gettext("Delete invitation")) - email = EmailField(lazy_gettext('Email'), validators=[DataRequired()]) + email = EmailField(lazy_gettext("Email"), validators=[DataRequired()]) + class DeleteAdminUnitMemberForm(FlaskForm): submit = SubmitField(lazy_gettext("Delete member")) - email = EmailField(lazy_gettext('Email'), validators=[DataRequired()]) + email = EmailField(lazy_gettext("Email"), validators=[DataRequired()]) + class UpdateAdminUnitMemberForm(FlaskForm): - roles = MultiCheckboxField(lazy_gettext('Roles')) + roles = MultiCheckboxField(lazy_gettext("Roles")) submit = SubmitField(lazy_gettext("Update member")) - diff --git a/project/forms/common.py b/project/forms/common.py index 1fc04ec..5ad8265 100644 --- a/project/forms/common.py +++ b/project/forms/common.py @@ -2,16 +2,25 @@ from flask_babelex import lazy_gettext from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileAllowed from wtforms import StringField, BooleanField, HiddenField -from wtforms.validators import DataRequired, Optional +from wtforms.validators import Optional import re import base64 + class BaseImageForm(FlaskForm): - copyright_text = StringField(lazy_gettext('Copyright text'), validators=[Optional()]) + copyright_text = StringField( + lazy_gettext("Copyright text"), validators=[Optional()] + ) + class FileImageForm(BaseImageForm): - image_file = FileField(lazy_gettext('File'), validators=[FileAllowed(['jpg', 'jpeg', 'png'], lazy_gettext('Images only!'))]) - delete_flag = BooleanField(lazy_gettext('Delete image'), default=False, validators=[Optional()]) + image_file = FileField( + lazy_gettext("File"), + validators=[FileAllowed(["jpg", "jpeg", "png"], lazy_gettext("Images only!"))], + ) + delete_flag = BooleanField( + lazy_gettext("Delete image"), default=False, validators=[Optional()] + ) def populate_obj(self, obj): super(BaseImageForm, self).populate_obj(obj) @@ -24,6 +33,7 @@ class FileImageForm(BaseImageForm): obj.data = None obj.encoding_format = None + class Base64ImageForm(BaseImageForm): image_base64 = HiddenField() @@ -31,8 +41,10 @@ class Base64ImageForm(BaseImageForm): super(BaseImageForm, self).process(formdata, obj, data, **kwargs) if self.image_base64.data is None and obj and obj.data: - base64_str = base64.b64encode(obj.data).decode('utf-8') - self.image_base64.data = 'data:{};base64,{}'.format(obj.encoding_format, base64_str) + base64_str = base64.b64encode(obj.data).decode("utf-8") + self.image_base64.data = "data:{};base64,{}".format( + obj.encoding_format, base64_str + ) def populate_obj(self, obj): super(BaseImageForm, self).populate_obj(obj) @@ -49,35 +61,36 @@ class Base64ImageForm(BaseImageForm): obj.data = None obj.encoding_format = None + event_rating_choices = [ - (0,lazy_gettext('0 (Little relevant)')), - (10,'1'), - (20,'2'), - (30,'3'), - (40,'4'), - (50,'5'), - (60,'6'), - (70,'7'), - (80,'8'), - (90,'9'), - (100,lazy_gettext('10 (Highlight)')) - ] + (0, lazy_gettext("0 (Little relevant)")), + (10, "1"), + (20, "2"), + (30, "3"), + (40, "4"), + (50, "5"), + (60, "6"), + (70, "7"), + (80, "8"), + (90, "9"), + (100, lazy_gettext("10 (Highlight)")), +] weekday_choices = [ - (1,lazy_gettext('Monday')), - (2,lazy_gettext('Tueday')), - (3,lazy_gettext('Wednesday')), - (4,lazy_gettext('Thursday')), - (5,lazy_gettext('Friday')), - (6,lazy_gettext('Saturday')), - (0,lazy_gettext('Sunday')) - ] + (1, lazy_gettext("Monday")), + (2, lazy_gettext("Tueday")), + (3, lazy_gettext("Wednesday")), + (4, lazy_gettext("Thursday")), + (5, lazy_gettext("Friday")), + (6, lazy_gettext("Saturday")), + (0, lazy_gettext("Sunday")), +] distance_choices = [ - (500,lazy_gettext('500 m')), - (5000,lazy_gettext('5 km')), - (10000,lazy_gettext('10 km')), - (25000,lazy_gettext('20 km')), - (50000,lazy_gettext('50 km')), - (100000,lazy_gettext('100 km')) - ] + (500, lazy_gettext("500 m")), + (5000, lazy_gettext("5 km")), + (10000, lazy_gettext("10 km")), + (25000, lazy_gettext("20 km")), + (50000, lazy_gettext("50 km")), + (100000, lazy_gettext("100 km")), +] diff --git a/project/forms/event.py b/project/forms/event.py index 4730e42..4bae0ec 100644 --- a/project/forms/event.py +++ b/project/forms/event.py @@ -1,100 +1,183 @@ from flask import request from flask_babelex import lazy_gettext, gettext from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from wtforms import SelectMultipleField, FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField -from wtforms.fields.html5 import DateTimeLocalField, EmailField, URLField +from wtforms import ( + SelectMultipleField, + RadioField, + StringField, + SubmitField, + TextAreaField, + SelectField, + BooleanField, + IntegerField, + FormField, +) +from wtforms.fields.html5 import EmailField, URLField from wtforms.validators import DataRequired, Optional -from wtforms.widgets import html_params, HTMLString -from project.models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus, Image +from project.models import ( + EventPlace, + EventTargetGroupOrigin, + EventAttendanceMode, + EventStatus, + Location, + EventOrganizer, + Image, +) from project.forms.common import event_rating_choices, Base64ImageForm from project.forms.widgets import CustomDateTimeField, CustomDateField + class EventPlaceLocationForm(FlaskForm): - street = StringField(lazy_gettext('Street'), validators=[Optional()]) - postalCode = StringField(lazy_gettext('Postal code'), validators=[Optional()]) - city = StringField(lazy_gettext('City'), validators=[Optional()]) + street = StringField(lazy_gettext("Street"), validators=[Optional()]) + postalCode = StringField(lazy_gettext("Postal code"), validators=[Optional()]) + city = StringField(lazy_gettext("City"), validators=[Optional()]) + class EventPlaceForm(FlaskForm): - name = StringField(lazy_gettext('Name'), validators=[Optional()]) + name = StringField(lazy_gettext("Name"), validators=[Optional()]) location = FormField(EventPlaceLocationForm, default=lambda: Location()) def populate_obj(self, obj): for name, field in self._fields.items(): - if name == 'location' and not obj.location: + if name == "location" and not obj.location: obj.location = Location() field.populate_obj(obj, name) + class OrganizerForm(EventPlaceForm): pass + class EventOrganizerForm(FlaskForm): - name = StringField(lazy_gettext('Organizator'), validators=[Optional()]) - url = URLField(lazy_gettext('Link URL'), validators=[Optional()]) - email = EmailField(lazy_gettext('Email'), validators=[Optional()]) - phone = StringField(lazy_gettext('Phone'), validators=[Optional()]) - fax = StringField(lazy_gettext('Fax'), validators=[Optional()]) + name = StringField(lazy_gettext("Organizator"), validators=[Optional()]) + url = URLField(lazy_gettext("Link URL"), validators=[Optional()]) + email = EmailField(lazy_gettext("Email"), validators=[Optional()]) + phone = StringField(lazy_gettext("Phone"), validators=[Optional()]) + fax = StringField(lazy_gettext("Fax"), validators=[Optional()]) + class BaseEventForm(FlaskForm): - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) - external_link = URLField(lazy_gettext('Link URL'), validators=[Optional()]) - ticket_link = StringField(lazy_gettext('Ticket Link URL'), validators=[Optional()]) - description = TextAreaField(lazy_gettext('Description'), validators=[DataRequired()]) - recurrence_rule = TextAreaField(lazy_gettext('Recurrence rule'), validators=[Optional()]) - start = CustomDateTimeField(lazy_gettext('Start'), validators=[DataRequired()]) - end = CustomDateTimeField(lazy_gettext('End'), validators=[Optional()]) - previous_start_date = CustomDateTimeField(lazy_gettext('Previous start date'), validators=[Optional()]) - tags = StringField(lazy_gettext('Tags'), validators=[Optional()]) - category_ids = SelectMultipleField(lazy_gettext('Categories'), validators=[DataRequired()], coerce=int) + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) + external_link = URLField(lazy_gettext("Link URL"), validators=[Optional()]) + ticket_link = StringField(lazy_gettext("Ticket Link URL"), validators=[Optional()]) + description = TextAreaField( + lazy_gettext("Description"), validators=[DataRequired()] + ) + recurrence_rule = TextAreaField( + lazy_gettext("Recurrence rule"), validators=[Optional()] + ) + start = CustomDateTimeField(lazy_gettext("Start"), validators=[DataRequired()]) + end = CustomDateTimeField(lazy_gettext("End"), validators=[Optional()]) + previous_start_date = CustomDateTimeField( + lazy_gettext("Previous start date"), validators=[Optional()] + ) + tags = StringField(lazy_gettext("Tags"), validators=[Optional()]) + category_ids = SelectMultipleField( + lazy_gettext("Categories"), validators=[DataRequired()], coerce=int + ) - kid_friendly = BooleanField(lazy_gettext('Kid friendly'), validators=[Optional()]) - accessible_for_free = BooleanField(lazy_gettext('Accessible for free'), validators=[Optional()]) - age_from = IntegerField(lazy_gettext('Typical Age from'), validators=[Optional()]) - age_to = IntegerField(lazy_gettext('Typical Age to'), validators=[Optional()]) - registration_required = BooleanField(lazy_gettext('Registration required'), validators=[Optional()]) - booked_up = BooleanField(lazy_gettext('Booked up'), validators=[Optional()]) - expected_participants = IntegerField(lazy_gettext('Expected number of participants'), validators=[Optional()]) - price_info = TextAreaField(lazy_gettext('Price info'), validators=[Optional()]) + kid_friendly = BooleanField(lazy_gettext("Kid friendly"), validators=[Optional()]) + accessible_for_free = BooleanField( + lazy_gettext("Accessible for free"), validators=[Optional()] + ) + age_from = IntegerField(lazy_gettext("Typical Age from"), validators=[Optional()]) + age_to = IntegerField(lazy_gettext("Typical Age to"), validators=[Optional()]) + registration_required = BooleanField( + lazy_gettext("Registration required"), validators=[Optional()] + ) + booked_up = BooleanField(lazy_gettext("Booked up"), validators=[Optional()]) + expected_participants = IntegerField( + lazy_gettext("Expected number of participants"), validators=[Optional()] + ) + price_info = TextAreaField(lazy_gettext("Price info"), validators=[Optional()]) - target_group_origin = SelectField(lazy_gettext('Target group origin'), coerce=int, choices=[ - (int(EventTargetGroupOrigin.both), lazy_gettext('EventTargetGroupOrigin.both')), - (int(EventTargetGroupOrigin.tourist), lazy_gettext('EventTargetGroupOrigin.tourist')), - (int(EventTargetGroupOrigin.resident), lazy_gettext('EventTargetGroupOrigin.resident'))]) + target_group_origin = SelectField( + lazy_gettext("Target group origin"), + coerce=int, + choices=[ + ( + int(EventTargetGroupOrigin.both), + lazy_gettext("EventTargetGroupOrigin.both"), + ), + ( + int(EventTargetGroupOrigin.tourist), + lazy_gettext("EventTargetGroupOrigin.tourist"), + ), + ( + int(EventTargetGroupOrigin.resident), + lazy_gettext("EventTargetGroupOrigin.resident"), + ), + ], + ) - attendance_mode = SelectField(lazy_gettext('Attendance mode'), coerce=int, choices=[ - (int(EventAttendanceMode.offline), lazy_gettext('EventAttendanceMode.offline')), - (int(EventAttendanceMode.online), lazy_gettext('EventAttendanceMode.online')), - (int(EventAttendanceMode.mixed), lazy_gettext('EventAttendanceMode.mixed'))]) + attendance_mode = SelectField( + lazy_gettext("Attendance mode"), + coerce=int, + choices=[ + ( + int(EventAttendanceMode.offline), + lazy_gettext("EventAttendanceMode.offline"), + ), + ( + int(EventAttendanceMode.online), + lazy_gettext("EventAttendanceMode.online"), + ), + (int(EventAttendanceMode.mixed), lazy_gettext("EventAttendanceMode.mixed")), + ], + ) + + photo = FormField(Base64ImageForm, lazy_gettext("Photo"), default=lambda: Image()) + rating = SelectField( + lazy_gettext("Rating"), default=50, coerce=int, choices=event_rating_choices + ) - photo = FormField(Base64ImageForm, lazy_gettext('Photo'), default=lambda: Image()) - rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices) class CreateEventForm(BaseEventForm): - event_place_choice = RadioField(lazy_gettext('Place'), choices=[(1,lazy_gettext('Select existing place')), (2,lazy_gettext('Enter new place'))], default=1, coerce=int) - event_place_id = SelectField(lazy_gettext('Place'), validators=[Optional()], coerce=int) + event_place_choice = RadioField( + lazy_gettext("Place"), + choices=[ + (1, lazy_gettext("Select existing place")), + (2, lazy_gettext("Enter new place")), + ], + default=1, + coerce=int, + ) + event_place_id = SelectField( + lazy_gettext("Place"), validators=[Optional()], coerce=int + ) new_event_place = FormField(EventPlaceForm, default=lambda: EventPlace()) - organizer_choice = RadioField(lazy_gettext('Organizer'), choices=[(1,lazy_gettext('Select existing organizer')), (2,lazy_gettext('Enter new organizer'))], default=1, coerce=int) - organizer_id = SelectField(lazy_gettext('Organizer'), validators=[Optional()], coerce=int) + organizer_choice = RadioField( + lazy_gettext("Organizer"), + choices=[ + (1, lazy_gettext("Select existing organizer")), + (2, lazy_gettext("Enter new organizer")), + ], + default=1, + coerce=int, + ) + organizer_id = SelectField( + lazy_gettext("Organizer"), validators=[Optional()], coerce=int + ) new_organizer = FormField(OrganizerForm, default=lambda: EventOrganizer()) submit = SubmitField(lazy_gettext("Create event")) def populate_obj(self, obj): for name, field in self._fields.items(): - if name == 'new_event_place': + if name == "new_event_place": if self.event_place_choice.data != 2: continue if not obj.event_place: obj.event_place = EventPlace() - field.populate_obj(obj, 'event_place') - elif name == 'new_organizer': + field.populate_obj(obj, "event_place") + elif name == "new_organizer": if self.organizer_choice.data != 2: continue if not obj.organizer: obj.organizer = EventOrganizer() - field.populate_obj(obj, 'organizer') - elif name == 'photo' and not obj.photo: + field.populate_obj(obj, "organizer") + elif name == "photo" and not obj.photo: obj.photo = Image() field.populate_obj(obj, name) @@ -102,50 +185,67 @@ class CreateEventForm(BaseEventForm): if not super(BaseEventForm, self).validate(): return False if self.event_place_id.data == 0 and not self.new_event_place.form.name.data: - msg = gettext('Select existing place or enter new place') + msg = gettext("Select existing place or enter new place") self.event_place_id.errors.append(msg) self.new_event_place.form.name.errors.append(msg) return False if self.organizer_id.data == 0 and not self.new_organizer.form.name.data: - msg = gettext('Select existing organizer or enter new organizer') + msg = gettext("Select existing organizer or enter new organizer") self.organizer_id.errors.append(msg) self.new_organizer.form.name.errors.append(msg) return False return True -class UpdateEventForm(BaseEventForm): - event_place_id = SelectField(lazy_gettext('Place'), validators=[DataRequired()], coerce=int) - organizer_id = SelectField(lazy_gettext('Organizer'), validators=[DataRequired()], coerce=int) - status = SelectField(lazy_gettext('Status'), coerce=int, choices=[ - (int(EventStatus.scheduled), lazy_gettext('EventStatus.scheduled')), - (int(EventStatus.cancelled), lazy_gettext('EventStatus.cancelled')), - (int(EventStatus.movedOnline), lazy_gettext('EventStatus.movedOnline')), - (int(EventStatus.postponed), lazy_gettext('EventStatus.postponed')), - (int(EventStatus.rescheduled), lazy_gettext('EventStatus.rescheduled'))]) +class UpdateEventForm(BaseEventForm): + event_place_id = SelectField( + lazy_gettext("Place"), validators=[DataRequired()], coerce=int + ) + organizer_id = SelectField( + lazy_gettext("Organizer"), validators=[DataRequired()], coerce=int + ) + + status = SelectField( + lazy_gettext("Status"), + coerce=int, + choices=[ + (int(EventStatus.scheduled), lazy_gettext("EventStatus.scheduled")), + (int(EventStatus.cancelled), lazy_gettext("EventStatus.cancelled")), + (int(EventStatus.movedOnline), lazy_gettext("EventStatus.movedOnline")), + (int(EventStatus.postponed), lazy_gettext("EventStatus.postponed")), + (int(EventStatus.rescheduled), lazy_gettext("EventStatus.rescheduled")), + ], + ) submit = SubmitField(lazy_gettext("Update event")) def populate_obj(self, obj): for name, field in self._fields.items(): - if name == 'photo' and not obj.photo: + if name == "photo" and not obj.photo: obj.photo = Image() field.populate_obj(obj, name) + class DeleteEventForm(FlaskForm): submit = SubmitField(lazy_gettext("Delete event")) - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) + class FindEventForm(FlaskForm): class Meta: csrf = False - date_from = CustomDateField(lazy_gettext('From'), validators=[Optional()]) - date_to = CustomDateField(lazy_gettext('to'), validators=[Optional()]) - keyword = StringField(lazy_gettext('Keyword'), validators=[Optional()]) - category_id = SelectField(lazy_gettext('Category'), validators=[Optional()], coerce=int) - organizer_id = SelectField(lazy_gettext('Organizer'), validators=[Optional()], coerce=int) + + date_from = CustomDateField(lazy_gettext("From"), validators=[Optional()]) + date_to = CustomDateField(lazy_gettext("to"), validators=[Optional()]) + keyword = StringField(lazy_gettext("Keyword"), validators=[Optional()]) + category_id = SelectField( + lazy_gettext("Category"), validators=[Optional()], coerce=int + ) + organizer_id = SelectField( + lazy_gettext("Organizer"), validators=[Optional()], coerce=int + ) submit = SubmitField(lazy_gettext("Find events")) def is_submitted(self): - return 'submit' in request.args + return "submit" in request.args diff --git a/project/forms/event_date.py b/project/forms/event_date.py index 5b8fe3b..ab790c9 100644 --- a/project/forms/event_date.py +++ b/project/forms/event_date.py @@ -1,28 +1,37 @@ from flask import request -from flask_babelex import lazy_gettext, gettext +from flask_babelex import lazy_gettext from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from wtforms import HiddenField, SelectMultipleField, FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField -from wtforms.fields.html5 import DateTimeLocalField, EmailField -from wtforms.validators import DataRequired, Optional -from wtforms.widgets import html_params, HTMLString -from project.models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus -from project.forms.common import event_rating_choices, weekday_choices, distance_choices -from project.forms.widgets import CustomDateField, MultiCheckboxField +from wtforms import ( + HiddenField, + StringField, + SubmitField, + SelectField, +) +from wtforms.validators import Optional +from project.forms.common import distance_choices +from project.forms.widgets import CustomDateField + class FindEventDateForm(FlaskForm): class Meta: csrf = False - date_from = CustomDateField(lazy_gettext('From'), validators=[Optional()]) - date_to = CustomDateField(lazy_gettext('to'), validators=[Optional()]) - keyword = StringField(lazy_gettext('Keyword'), validators=[Optional()]) - category_id = SelectField(lazy_gettext('Category'), validators=[Optional()], coerce=int) + date_from = CustomDateField(lazy_gettext("From"), validators=[Optional()]) + date_to = CustomDateField(lazy_gettext("to"), validators=[Optional()]) + keyword = StringField(lazy_gettext("Keyword"), validators=[Optional()]) + category_id = SelectField( + lazy_gettext("Category"), validators=[Optional()], coerce=int + ) coordinate = HiddenField(validators=[Optional()]) - location = StringField(lazy_gettext('Location'), validators=[Optional()]) - distance = SelectField(lazy_gettext('Distance'), validators=[Optional()], coerce=int, choices=distance_choices) + location = StringField(lazy_gettext("Location"), validators=[Optional()]) + distance = SelectField( + lazy_gettext("Distance"), + validators=[Optional()], + coerce=int, + choices=distance_choices, + ) submit = SubmitField(lazy_gettext("Find")) def is_submitted(self): - return 'submit' in request.args \ No newline at end of file + return "submit" in request.args diff --git a/project/forms/event_place.py b/project/forms/event_place.py index acea9ca..ff1eb4e 100644 --- a/project/forms/event_place.py +++ b/project/forms/event_place.py @@ -1,48 +1,62 @@ -from flask_babelex import lazy_gettext, gettext +from flask_babelex import lazy_gettext from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from wtforms import DecimalField, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField -from wtforms.fields.html5 import DateTimeLocalField, EmailField, URLField +from wtforms import ( + DecimalField, + StringField, + SubmitField, + TextAreaField, + FormField, +) +from wtforms.fields.html5 import URLField from wtforms.validators import DataRequired, Optional -from wtforms.widgets import html_params, HTMLString -import decimal from project.models import Location, Image from project.forms.common import FileImageForm + class EventPlaceLocationForm(FlaskForm): - street = StringField(lazy_gettext('Street'), validators=[Optional()]) - postalCode = StringField(lazy_gettext('Postal code'), validators=[Optional()]) - city = StringField(lazy_gettext('City'), validators=[Optional()]) - state = StringField(lazy_gettext('State'), validators=[Optional()]) - latitude = DecimalField(lazy_gettext('Latitude'), places=16, validators=[Optional()]) - longitude = DecimalField(lazy_gettext('Longitude'), places=16, validators=[Optional()]) + street = StringField(lazy_gettext("Street"), validators=[Optional()]) + postalCode = StringField(lazy_gettext("Postal code"), validators=[Optional()]) + city = StringField(lazy_gettext("City"), validators=[Optional()]) + state = StringField(lazy_gettext("State"), validators=[Optional()]) + latitude = DecimalField( + lazy_gettext("Latitude"), places=16, validators=[Optional()] + ) + longitude = DecimalField( + lazy_gettext("Longitude"), places=16, validators=[Optional()] + ) + class BaseEventPlaceForm(FlaskForm): - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) - url = URLField(lazy_gettext('Link URL'), validators=[Optional()]) - photo = FormField(FileImageForm, lazy_gettext('Photo'), default=lambda: Image()) - description = TextAreaField(lazy_gettext('Description'), validators=[Optional()]) + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) + url = URLField(lazy_gettext("Link URL"), validators=[Optional()]) + photo = FormField(FileImageForm, lazy_gettext("Photo"), default=lambda: Image()) + description = TextAreaField(lazy_gettext("Description"), validators=[Optional()]) location = FormField(EventPlaceLocationForm) def populate_obj(self, obj): for name, field in self._fields.items(): - if name == 'location' and not obj.location: + if name == "location" and not obj.location: obj.location = Location() - elif name == 'photo' and not obj.photo: + elif name == "photo" and not obj.photo: obj.photo = Image() field.populate_obj(obj, name) + class CreateEventPlaceForm(BaseEventPlaceForm): submit = SubmitField(lazy_gettext("Create place")) + class UpdateEventPlaceForm(BaseEventPlaceForm): submit = SubmitField(lazy_gettext("Update place")) + class DeleteEventPlaceForm(FlaskForm): submit = SubmitField(lazy_gettext("Delete place")) - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) + class FindEventPlaceForm(FlaskForm): class Meta: csrf = False + submit = SubmitField(lazy_gettext("Find places")) diff --git a/project/forms/event_suggestion.py b/project/forms/event_suggestion.py index af5bbea..9185ac0 100644 --- a/project/forms/event_suggestion.py +++ b/project/forms/event_suggestion.py @@ -1,52 +1,135 @@ -from flask import request -from flask_babelex import lazy_gettext, gettext +from flask_babelex import lazy_gettext from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from wtforms import FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField -from wtforms.fields.html5 import DateTimeLocalField, EmailField, TelField, URLField +from wtforms import ( + StringField, + SubmitField, + TextAreaField, + SelectField, + BooleanField, + FormField, +) +from wtforms.fields.html5 import EmailField, TelField, URLField from wtforms.validators import DataRequired, Optional -from wtforms.widgets import html_params, HTMLString -from project.models import EventSuggestion, EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus, Image -from project.forms.common import event_rating_choices, Base64ImageForm -from project.forms.widgets import CustomDateTimeField, CustomDateField, TagSelectField -from project.forms.common import event_rating_choices +from project.models import ( + EventRejectionReason, + Image, +) +from project.forms.common import Base64ImageForm +from project.forms.widgets import CustomDateTimeField, TagSelectField + class CreateEventSuggestionForm(FlaskForm): - name = StringField(lazy_gettext('Name'), validators=[DataRequired()], description=lazy_gettext('Enter a short, meaningful name for the event.')) - start = CustomDateTimeField(lazy_gettext('Start'), validators=[DataRequired()], description=lazy_gettext('Indicate when the event will take place.')) - description = TextAreaField(lazy_gettext('Description'), validators=[Optional()], description=lazy_gettext('Add an optional description of the event.')) - external_link = URLField(lazy_gettext('Link URL'), validators=[Optional()], description=lazy_gettext('Add an optional link. That can make the review easier.')) + name = StringField( + lazy_gettext("Name"), + validators=[DataRequired()], + description=lazy_gettext("Enter a short, meaningful name for the event."), + ) + start = CustomDateTimeField( + lazy_gettext("Start"), + validators=[DataRequired()], + description=lazy_gettext("Indicate when the event will take place."), + ) + description = TextAreaField( + lazy_gettext("Description"), + validators=[Optional()], + description=lazy_gettext("Add an optional description of the event."), + ) + external_link = URLField( + lazy_gettext("Link URL"), + validators=[Optional()], + description=lazy_gettext( + "Add an optional link. That can make the review easier." + ), + ) - contact_name = StringField(lazy_gettext('Name'), validators=[DataRequired()], description=lazy_gettext('Please enter your name for the review.')) - contact_phone = TelField(lazy_gettext('Phone'), validators=[Optional()], description=lazy_gettext('Please enter your phone number or email address for the review.')) - contact_email = EmailField(lazy_gettext('Email'), validators=[Optional()], description=lazy_gettext('Please enter your email address or phone number for the review.')) - contact_email_notice = BooleanField(lazy_gettext('I would like to be notified by email after the review'), validators=[Optional()]) + contact_name = StringField( + lazy_gettext("Name"), + validators=[DataRequired()], + description=lazy_gettext("Please enter your name for the review."), + ) + contact_phone = TelField( + lazy_gettext("Phone"), + validators=[Optional()], + description=lazy_gettext( + "Please enter your phone number or email address for the review." + ), + ) + contact_email = EmailField( + lazy_gettext("Email"), + validators=[Optional()], + description=lazy_gettext( + "Please enter your email address or phone number for the review." + ), + ) + contact_email_notice = BooleanField( + lazy_gettext("I would like to be notified by email after the review"), + validators=[Optional()], + ) - event_place_id = TagSelectField(lazy_gettext('Place'), validators=[DataRequired()], description=lazy_gettext('Choose where the event takes place. If the venue is not yet in the list, just enter it.')) - organizer_id = TagSelectField(lazy_gettext('Organizer'), validators=[DataRequired()], description=lazy_gettext('Select the organizer. If the organizer is not yet on the list, just enter it.')) - photo = FormField(Base64ImageForm, lazy_gettext('Photo'), default=lambda: Image(), description=lazy_gettext('We recommend uploading a photo for the event. It looks a lot more, but of course it works without it.')) - accept_tos = BooleanField(lazy_gettext('I confirm that I have clarified all information (text, images, etc.) that I upload into the system with regard to their rights of use and declare that they may be passed on.'), validators=[DataRequired()]) + event_place_id = TagSelectField( + lazy_gettext("Place"), + validators=[DataRequired()], + description=lazy_gettext( + "Choose where the event takes place. If the venue is not yet in the list, just enter it." + ), + ) + organizer_id = TagSelectField( + lazy_gettext("Organizer"), + validators=[DataRequired()], + description=lazy_gettext( + "Select the organizer. If the organizer is not yet on the list, just enter it." + ), + ) + photo = FormField( + Base64ImageForm, + lazy_gettext("Photo"), + default=lambda: Image(), + description=lazy_gettext( + "We recommend uploading a photo for the event. It looks a lot more, but of course it works without it." + ), + ) + accept_tos = BooleanField( + lazy_gettext( + "I confirm that I have clarified all information (text, images, etc.) that I upload into the system with regard to their rights of use and declare that they may be passed on." + ), + validators=[DataRequired()], + ) submit = SubmitField(lazy_gettext("Create event suggestion")) def populate_obj(self, obj): for name, field in self._fields.items(): - if name == 'photo' and not obj.photo: + if name == "photo" and not obj.photo: obj.photo = Image() - if name == 'event_place_id' and self.event_place_id.is_free_text(): + if name == "event_place_id" and self.event_place_id.is_free_text(): obj.event_place_text = self.event_place_id.data obj.event_place_id = None - elif name == 'organizer_id' and self.organizer_id.is_free_text(): + elif name == "organizer_id" and self.organizer_id.is_free_text(): obj.organizer_text = self.organizer_id.data obj.organizer_id = None else: field.populate_obj(obj, name) + class RejectEventSuggestionForm(FlaskForm): - rejection_resaon = SelectField(lazy_gettext('Rejection reason'), coerce=int, choices=[ - (0, ''), - (int(EventRejectionReason.duplicate), lazy_gettext('EventRejectionReason.duplicate')), - (int(EventRejectionReason.untrustworthy), lazy_gettext('EventRejectionReason.untrustworthy')), - (int(EventRejectionReason.illegal), lazy_gettext('EventRejectionReason.illegal'))]) + rejection_resaon = SelectField( + lazy_gettext("Rejection reason"), + coerce=int, + choices=[ + (0, ""), + ( + int(EventRejectionReason.duplicate), + lazy_gettext("EventRejectionReason.duplicate"), + ), + ( + int(EventRejectionReason.untrustworthy), + lazy_gettext("EventRejectionReason.untrustworthy"), + ), + ( + int(EventRejectionReason.illegal), + lazy_gettext("EventRejectionReason.illegal"), + ), + ], + ) submit = SubmitField(lazy_gettext("Reject event suggestion")) diff --git a/project/forms/organizer.py b/project/forms/organizer.py index e968c2e..0cfebed 100644 --- a/project/forms/organizer.py +++ b/project/forms/organizer.py @@ -1,44 +1,56 @@ from flask_babelex import lazy_gettext from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from wtforms import StringField, SubmitField, DecimalField, TextAreaField, FormField, SelectField +from wtforms import ( + StringField, + SubmitField, + DecimalField, + FormField, +) from wtforms.fields.html5 import EmailField, TelField, URLField -from wtforms.validators import DataRequired, Optional, Regexp -import decimal +from wtforms.validators import DataRequired, Optional from project.models import Location, Image from project.forms.common import FileImageForm + class OrganizerLocationForm(FlaskForm): - street = StringField(lazy_gettext('Street'), validators=[Optional()]) - postalCode = StringField(lazy_gettext('Postal code'), validators=[Optional()]) - city = StringField(lazy_gettext('City'), validators=[Optional()]) - state = StringField(lazy_gettext('State'), validators=[Optional()]) - latitude = DecimalField(lazy_gettext('Latitude'), places=16, validators=[Optional()]) - longitude = DecimalField(lazy_gettext('Longitude'), places=16, validators=[Optional()]) + street = StringField(lazy_gettext("Street"), validators=[Optional()]) + postalCode = StringField(lazy_gettext("Postal code"), validators=[Optional()]) + city = StringField(lazy_gettext("City"), validators=[Optional()]) + state = StringField(lazy_gettext("State"), validators=[Optional()]) + latitude = DecimalField( + lazy_gettext("Latitude"), places=16, validators=[Optional()] + ) + longitude = DecimalField( + lazy_gettext("Longitude"), places=16, validators=[Optional()] + ) + class BaseOrganizerForm(FlaskForm): - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) - url = URLField(lazy_gettext('Link URL'), validators=[Optional()]) - email = EmailField(lazy_gettext('Email'), validators=[Optional()]) - phone = TelField(lazy_gettext('Phone'), validators=[Optional()]) - fax = TelField(lazy_gettext('Fax'), validators=[Optional()]) - logo = FormField(FileImageForm, lazy_gettext('Logo'), default=lambda: Image()) + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) + url = URLField(lazy_gettext("Link URL"), validators=[Optional()]) + email = EmailField(lazy_gettext("Email"), validators=[Optional()]) + phone = TelField(lazy_gettext("Phone"), validators=[Optional()]) + fax = TelField(lazy_gettext("Fax"), validators=[Optional()]) + logo = FormField(FileImageForm, lazy_gettext("Logo"), default=lambda: Image()) location = FormField(OrganizerLocationForm) def populate_obj(self, obj): for name, field in self._fields.items(): - if name == 'location' and not obj.location: + if name == "location" and not obj.location: obj.location = Location() - elif name == 'logo' and not obj.logo: + elif name == "logo" and not obj.logo: obj.logo = Image() field.populate_obj(obj, name) + class CreateOrganizerForm(BaseOrganizerForm): submit = SubmitField(lazy_gettext("Create organizer")) + class UpdateOrganizerForm(BaseOrganizerForm): submit = SubmitField(lazy_gettext("Update organizer")) + class DeleteOrganizerForm(FlaskForm): submit = SubmitField(lazy_gettext("Delete organizer")) - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) \ No newline at end of file + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) diff --git a/project/forms/planing.py b/project/forms/planing.py index 12bdf48..01197a9 100644 --- a/project/forms/planing.py +++ b/project/forms/planing.py @@ -1,28 +1,37 @@ from flask import request -from flask_babelex import lazy_gettext, gettext +from flask_babelex import lazy_gettext from flask_wtf import FlaskForm -from flask_wtf.file import FileField, FileAllowed -from wtforms import HiddenField, SelectMultipleField, FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField -from wtforms.fields.html5 import DateTimeLocalField, EmailField -from wtforms.validators import DataRequired, Optional -from wtforms.widgets import html_params, HTMLString -from project.models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus -from project.forms.common import event_rating_choices, weekday_choices, distance_choices +from wtforms import HiddenField, StringField, SubmitField, SelectField +from wtforms.validators import Optional +from project.forms.common import weekday_choices, distance_choices from project.forms.widgets import CustomDateField, MultiCheckboxField + class PlaningForm(FlaskForm): class Meta: csrf = False - date_from = CustomDateField(lazy_gettext('From'), validators=[Optional()]) - date_to = CustomDateField(lazy_gettext('to'), validators=[Optional()]) - category_id = SelectField(lazy_gettext('Category'), validators=[Optional()], coerce=int) + date_from = CustomDateField(lazy_gettext("From"), validators=[Optional()]) + date_to = CustomDateField(lazy_gettext("to"), validators=[Optional()]) + category_id = SelectField( + lazy_gettext("Category"), validators=[Optional()], coerce=int + ) coordinate = HiddenField(validators=[Optional()]) - location = StringField(lazy_gettext('Location'), validators=[Optional()]) - distance = SelectField(lazy_gettext('Distance'), validators=[Optional()], coerce=int, choices=distance_choices) - weekday = MultiCheckboxField(lazy_gettext('Weekdays'), validators=[Optional()], coerce=int, choices=weekday_choices) + location = StringField(lazy_gettext("Location"), validators=[Optional()]) + distance = SelectField( + lazy_gettext("Distance"), + validators=[Optional()], + coerce=int, + choices=distance_choices, + ) + weekday = MultiCheckboxField( + lazy_gettext("Weekdays"), + validators=[Optional()], + coerce=int, + choices=weekday_choices, + ) submit = SubmitField(lazy_gettext("Find")) def is_submitted(self): - return 'submit' in request.args \ No newline at end of file + return "submit" in request.args diff --git a/project/forms/reference.py b/project/forms/reference.py index 4ea4b0c..e2dff4a 100644 --- a/project/forms/reference.py +++ b/project/forms/reference.py @@ -1,18 +1,27 @@ -from flask_babelex import lazy_gettext, gettext +from flask_babelex import lazy_gettext from flask_wtf import FlaskForm from wtforms import SelectField, StringField, SubmitField from wtforms.validators import DataRequired from project.forms.common import event_rating_choices + class CreateEventReferenceForm(FlaskForm): - admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int) - rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices) + admin_unit_id = SelectField( + lazy_gettext("Admin unit"), validators=[DataRequired()], coerce=int + ) + rating = SelectField( + lazy_gettext("Rating"), default=50, coerce=int, choices=event_rating_choices + ) submit = SubmitField(lazy_gettext("Save reference")) + class UpdateEventReferenceForm(FlaskForm): - rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices) + rating = SelectField( + lazy_gettext("Rating"), default=50, coerce=int, choices=event_rating_choices + ) submit = SubmitField(lazy_gettext("Update reference")) + class DeleteReferenceForm(FlaskForm): submit = SubmitField(lazy_gettext("Delete reference")) - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) \ No newline at end of file + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) diff --git a/project/forms/reference_request.py b/project/forms/reference_request.py index 0094bf9..8c34d93 100644 --- a/project/forms/reference_request.py +++ b/project/forms/reference_request.py @@ -1,30 +1,71 @@ -from flask_babelex import lazy_gettext, gettext +from flask_babelex import lazy_gettext from flask_wtf import FlaskForm from wtforms import SelectField, StringField, SubmitField from wtforms.validators import DataRequired from project.forms.common import event_rating_choices -from project.models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus +from project.models import ( + EventReferenceRequestRejectionReason, + EventReferenceRequestReviewStatus, +) + class CreateEventReferenceRequestForm(FlaskForm): - admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int) + admin_unit_id = SelectField( + lazy_gettext("Admin unit"), validators=[DataRequired()], coerce=int + ) submit = SubmitField(lazy_gettext("Save request")) + class DeleteReferenceRequestForm(FlaskForm): submit = SubmitField(lazy_gettext("Delete request")) - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) + name = StringField(lazy_gettext("Name"), validators=[DataRequired()]) + class ReferenceRequestReviewForm(FlaskForm): - review_status = SelectField(lazy_gettext('Review status'), coerce=int, choices=[ - (int(EventReferenceRequestReviewStatus.inbox), lazy_gettext('EventReferenceRequestReviewStatus.inbox')), - (int(EventReferenceRequestReviewStatus.verified), lazy_gettext('EventReferenceRequestReviewStatus.verified')), - (int(EventReferenceRequestReviewStatus.rejected), lazy_gettext('EventReferenceRequestReviewStatus.rejected'))]) + review_status = SelectField( + lazy_gettext("Review status"), + coerce=int, + choices=[ + ( + int(EventReferenceRequestReviewStatus.inbox), + lazy_gettext("EventReferenceRequestReviewStatus.inbox"), + ), + ( + int(EventReferenceRequestReviewStatus.verified), + lazy_gettext("EventReferenceRequestReviewStatus.verified"), + ), + ( + int(EventReferenceRequestReviewStatus.rejected), + lazy_gettext("EventReferenceRequestReviewStatus.rejected"), + ), + ], + ) - rejection_reason = SelectField(lazy_gettext('Rejection reason'), coerce=int, choices=[ - (0, ''), - (int(EventReferenceRequestRejectionReason.duplicate), lazy_gettext('EventReferenceRequestRejectionReason.duplicate')), - (int(EventReferenceRequestRejectionReason.untrustworthy), lazy_gettext('EventReferenceRequestRejectionReason.untrustworthy')), - (int(EventReferenceRequestRejectionReason.irrelevant), lazy_gettext('EventReferenceRequestRejectionReason.irrelevant')), - (int(EventReferenceRequestRejectionReason.illegal), lazy_gettext('EventReferenceRequestRejectionReason.illegal'))]) + rejection_reason = SelectField( + lazy_gettext("Rejection reason"), + coerce=int, + choices=[ + (0, ""), + ( + int(EventReferenceRequestRejectionReason.duplicate), + lazy_gettext("EventReferenceRequestRejectionReason.duplicate"), + ), + ( + int(EventReferenceRequestRejectionReason.untrustworthy), + lazy_gettext("EventReferenceRequestRejectionReason.untrustworthy"), + ), + ( + int(EventReferenceRequestRejectionReason.irrelevant), + lazy_gettext("EventReferenceRequestRejectionReason.irrelevant"), + ), + ( + int(EventReferenceRequestRejectionReason.illegal), + lazy_gettext("EventReferenceRequestRejectionReason.illegal"), + ), + ], + ) - rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices) - submit = SubmitField(lazy_gettext("Save review")) \ No newline at end of file + rating = SelectField( + lazy_gettext("Rating"), default=50, coerce=int, choices=event_rating_choices + ) + submit = SubmitField(lazy_gettext("Save review")) diff --git a/project/forms/widgets.py b/project/forms/widgets.py index b318212..c43295d 100644 --- a/project/forms/widgets.py +++ b/project/forms/widgets.py @@ -1,15 +1,16 @@ from wtforms import DateTimeField, SelectMultipleField, SelectField from wtforms.widgets import html_params, HTMLString, ListWidget, CheckboxInput from wtforms.validators import StopValidation -import pytz from datetime import datetime from flask_babelex import to_user_timezone, gettext from project.dateutils import berlin_tz + class MultiCheckboxField(SelectMultipleField): widget = ListWidget(prefix_label=False) option_widget = CheckboxInput() + def create_option_string(count, value): result = "" for i in range(count): @@ -17,10 +18,11 @@ def create_option_string(count, value): result = result + '' % (i, selected, i) return result + class CustomDateTimeWidget: def __call__(self, field, **kwargs): - id = kwargs.pop('id', field.id) - date = '' + id = kwargs.pop("id", field.id) + date = "" hour = minute = 0 if field.data: date_value = to_user_timezone(field.data) @@ -28,12 +30,24 @@ class CustomDateTimeWidget: hour = date_value.hour minute = date_value.minute - date_params = html_params(name=field.name, id=id, value=date, required=field.flags.required, **kwargs) - time_hour_params = html_params(name=field.name, id=id + '-hour', **kwargs) - time_minute_params = html_params(name=field.name, id=id + '-minute', **kwargs) - clear_button_id = id + '-clear-button' + date_params = html_params( + name=field.name, id=id, value=date, required=field.flags.required, **kwargs + ) + time_hour_params = html_params(name=field.name, id=id + "-hour", **kwargs) + time_minute_params = html_params(name=field.name, id=id + "-minute", **kwargs) + clear_button_id = id + "-clear-button" + + return HTMLString( + '
:
'.format( + date_params, + clear_button_id, + time_hour_params, + create_option_string(24, hour), + time_minute_params, + create_option_string(60, minute), + ) + ) - return HTMLString('
:
'.format(date_params, clear_button_id, time_hour_params, create_option_string(24, hour), time_minute_params, create_option_string(60, minute))) class CustomDateTimeField(DateTimeField): widget = CustomDateTimeWidget() @@ -47,15 +61,20 @@ class CustomDateTimeField(DateTimeField): return date = datetime.strptime(date_str, "%Y-%m-%d") - date_time = datetime(date.year, date.month, date.day, int(hour_str), int(minute_str)) + date_time = datetime( + date.year, date.month, date.day, int(hour_str), int(minute_str) + ) self.data = berlin_tz.localize(date_time) - except: - raise ValueError('Not a valid datetime value. Looking for YYYY-MM-DD HH:mm.') + except Exception: + raise ValueError( + "Not a valid datetime value. Looking for YYYY-MM-DD HH:mm." + ) + class CustomDateWidget: def __call__(self, field, **kwargs): - id = kwargs.pop('id', field.id) - date = '' + id = kwargs.pop("id", field.id) + date = "" if field.data: date_value = to_user_timezone(field.data) date = date_value.strftime("%Y-%m-%d") @@ -63,6 +82,7 @@ class CustomDateWidget: date_params = html_params(name=field.name, id=id, value=date, **kwargs) return HTMLString(''.format(date_params)) + class CustomDateField(DateTimeField): widget = CustomDateWidget() @@ -76,8 +96,9 @@ class CustomDateField(DateTimeField): date = datetime.strptime(date_str, "%Y-%m-%d") self.data = berlin_tz.localize(date) - except: - raise ValueError('Not a valid date value. Looking for YYYY-MM-DD.') + except Exception: + raise ValueError("Not a valid date value. Looking for YYYY-MM-DD.") + def try_to_int(value): if isinstance(value, int): @@ -91,15 +112,25 @@ def try_to_int(value): return value -class TagSelectField(SelectField): - def __init__(self, label=None, validators=None, coerce=try_to_int, choices=None, validate_choice=True, **kwargs): - super(TagSelectField, self).__init__(label, validators, coerce, choices, validate_choice, **kwargs) +class TagSelectField(SelectField): + def __init__( + self, + label=None, + validators=None, + coerce=try_to_int, + choices=None, + validate_choice=True, + **kwargs + ): + super(TagSelectField, self).__init__( + label, validators, coerce, choices, validate_choice, **kwargs + ) def pre_validate(self, form): if self.is_free_text(): if not self.data or not self.data.strip(): - raise StopValidation(gettext('This field is required')) + raise StopValidation(gettext("This field is required")) else: super(TagSelectField, self).pre_validate(form) diff --git a/project/i10n.py b/project/i10n.py index 5595cb3..f520d47 100644 --- a/project/i10n.py +++ b/project/i10n.py @@ -1,32 +1,35 @@ from project import app, babel +from flask_babelex import gettext from flask import request + @babel.localeselector def get_locale(): - return request.accept_languages.best_match(app.config['LANGUAGES']) + return request.accept_languages.best_match(app.config["LANGUAGES"]) + def print_dynamic_texts(): - gettext('Event_Art') - gettext('Event_Book') - gettext('Event_Movie') - gettext('Event_Family') - gettext('Event_Festival') - gettext('Event_Religious') - gettext('Event_Shopping') - gettext('Event_Comedy') - gettext('Event_Music') - gettext('Event_Dance') - gettext('Event_Nightlife') - gettext('Event_Theater') - gettext('Event_Dining') - gettext('Event_Conference') - gettext('Event_Meetup') - gettext('Event_Fitness') - gettext('Event_Sports') - gettext('Event_Other') - gettext('Typical Age range') - gettext('Administrator') - gettext('Event expert') - gettext('EventReviewStatus.inbox') - gettext('EventReviewStatus.verified') - gettext('EventReviewStatus.rejected') \ No newline at end of file + gettext("Event_Art") + gettext("Event_Book") + gettext("Event_Movie") + gettext("Event_Family") + gettext("Event_Festival") + gettext("Event_Religious") + gettext("Event_Shopping") + gettext("Event_Comedy") + gettext("Event_Music") + gettext("Event_Dance") + gettext("Event_Nightlife") + gettext("Event_Theater") + gettext("Event_Dining") + gettext("Event_Conference") + gettext("Event_Meetup") + gettext("Event_Fitness") + gettext("Event_Sports") + gettext("Event_Other") + gettext("Typical Age range") + gettext("Administrator") + gettext("Event expert") + gettext("EventReviewStatus.inbox") + gettext("EventReviewStatus.verified") + gettext("EventReviewStatus.rejected") diff --git a/project/init_data.py b/project/init_data.py index a61163a..dc16803 100644 --- a/project/init_data.py +++ b/project/init_data.py @@ -3,6 +3,7 @@ from project.services.user import upsert_user_role, add_roles_to_user from project.services.admin_unit import upsert_admin_unit_member_role from project.models import Location + @app.before_first_request def create_initial_data(): admin_permissions = [ @@ -10,7 +11,8 @@ def create_initial_data(): "admin_unit.members:invite", "admin_unit.members:read", "admin_unit.members:update", - "admin_unit.members:delete"] + "admin_unit.members:delete", + ] event_permissions = [ "event:verify", "event:create", @@ -31,15 +33,16 @@ def create_initial_data(): "reference_request:read", "reference_request:update", "reference_request:delete", - "reference_request:verify"] + "reference_request:verify", + ] - upsert_admin_unit_member_role('admin', 'Administrator', admin_permissions) - upsert_admin_unit_member_role('event_verifier', 'Event expert', event_permissions) + upsert_admin_unit_member_role("admin", "Administrator", admin_permissions) + upsert_admin_unit_member_role("event_verifier", "Event expert", event_permissions) - upsert_user_role('admin', 'Administrator', admin_permissions) - upsert_user_role('event_verifier', 'Event expert', event_permissions) - add_roles_to_user('grams.daniel@gmail.com', ['admin', 'event_verifier']) + upsert_user_role("admin", "Administrator", admin_permissions) + upsert_user_role("event_verifier", "Event expert", event_permissions) + add_roles_to_user("grams.daniel@gmail.com", ["admin", "event_verifier"]) Location.update_coordinates() - db.session.commit() \ No newline at end of file + db.session.commit() diff --git a/project/jinja_filters.py b/project/jinja_filters.py index 801b40e..c901a7f 100644 --- a/project/jinja_filters.py +++ b/project/jinja_filters.py @@ -3,31 +3,37 @@ from project.utils import get_event_category_name, get_localized_enum_name from urllib.parse import quote_plus import os -def env_override(value, key): - return os.getenv(key, value) -app.jinja_env.filters['event_category_name'] = lambda u: get_event_category_name(u) -app.jinja_env.filters['loc_enum'] = lambda u: get_localized_enum_name(u) -app.jinja_env.filters['env_override'] = env_override -app.jinja_env.filters['quote_plus'] = lambda u: quote_plus(u) +def env_override(value, key): + return os.getenv(key, value) + + +app.jinja_env.filters["event_category_name"] = lambda u: get_event_category_name(u) +app.jinja_env.filters["loc_enum"] = lambda u: get_localized_enum_name(u) +app.jinja_env.filters["env_override"] = env_override +app.jinja_env.filters["quote_plus"] = lambda u: quote_plus(u) + @app.context_processor def get_manage_menu_options_context_processor(): + def get_manage_menu_options(admin_unit): + from project.access import has_access + from project.services.event_suggestion import get_event_reviews_badge_query + from project.services.reference import ( + get_reference_requests_incoming_badge_query, + ) - def get_manage_menu_options(admin_unit): - from project.access import has_access - from project.services.event_suggestion import get_event_reviews_badge_query - from project.services.reference import get_reference_requests_incoming_badge_query + reviews_badge = 0 + reference_requests_incoming_badge = get_reference_requests_incoming_badge_query( + admin_unit + ).count() - reviews_badge = 0 - reference_requests_incoming_badge = get_reference_requests_incoming_badge_query(admin_unit).count() + if has_access(admin_unit, "event:verify"): + reviews_badge = get_event_reviews_badge_query(admin_unit).count() - if has_access(admin_unit, 'event:verify'): - reviews_badge = get_event_reviews_badge_query(admin_unit).count() + return { + "reviews_badge": reviews_badge, + "reference_requests_incoming_badge": reference_requests_incoming_badge, + } - return { - 'reviews_badge': reviews_badge, - 'reference_requests_incoming_badge': reference_requests_incoming_badge - } - - return dict(get_manage_menu_options=get_manage_menu_options) \ No newline at end of file + return dict(get_manage_menu_options=get_manage_menu_options) diff --git a/project/jsonld.py b/project/jsonld.py index 89efb63..6fb6be5 100644 --- a/project/jsonld.py +++ b/project/jsonld.py @@ -5,16 +5,17 @@ from flask import url_for from project.models import EventAttendanceMode, EventStatus import pytz -berlin_tz = pytz.timezone('Europe/Berlin') +berlin_tz = pytz.timezone("Europe/Berlin") + -# subclass JSONEncoder class DateTimeEncoder(JSONEncoder): - #Override the default method - def default(self, obj): - if isinstance(obj, (datetime.date, datetime.datetime)): - return (obj.astimezone(berlin_tz)).isoformat() - if isinstance(obj, decimal.Decimal): - return float(obj) + # Override the default method + def default(self, obj): + if isinstance(obj, (datetime.date, datetime.datetime)): + return (obj.astimezone(berlin_tz)).isoformat() + if isinstance(obj, decimal.Decimal): + return float(obj) + def get_sd_for_admin_unit(admin_unit): result = {} @@ -27,6 +28,7 @@ def get_sd_for_admin_unit(admin_unit): return result + def get_sd_for_organizer_organization(organizer): result = {} result["@type"] = "Organization" @@ -46,9 +48,11 @@ def get_sd_for_organizer_organization(organizer): return result + def get_sd_for_organizer(organizer): return get_sd_for_organizer_organization(organizer) + def get_sd_for_location(location): result = {} result["@type"] = "PostalAddress" @@ -63,6 +67,7 @@ def get_sd_for_location(location): return result + def get_sd_for_geo(location): result = {} result["@type"] = "GeoCoordinates" @@ -70,6 +75,7 @@ def get_sd_for_geo(location): result["longitude"] = location.longitude return result + def get_sd_for_place(place, use_ref=True): result = {} result["@type"] = "Place" @@ -82,13 +88,14 @@ def get_sd_for_place(place, use_ref=True): result["geo"] = get_sd_for_geo(place.location) if place.photo_id: - result["photo"] = url_for('image', id=place.photo_id) + result["photo"] = url_for("image", id=place.photo_id) if place.url: result["url"] = place.url return result + def get_sd_for_event_date(event_date): event = event_date.event @@ -101,7 +108,7 @@ def get_sd_for_event_date(event_date): result["startDate"] = event_date.start url_list = list() - url_list.append(url_for('event_date', id=event_date.id)) + url_list.append(url_for("event_date", id=event_date.id)) if event.external_link: url_list.append(event.external_link) @@ -157,6 +164,6 @@ def get_sd_for_event_date(event_date): result["eventStatus"] = "EventRescheduled" if event.photo_id: - result["image"] = url_for('image', id=event.photo_id) + result["image"] = url_for("image", id=event.photo_id) return result diff --git a/project/models.py b/project/models.py index 6e501a4..ed13717 100644 --- a/project/models.py +++ b/project/models.py @@ -3,9 +3,19 @@ from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import relationship, backref, deferred from sqlalchemy.schema import CheckConstraint -from sqlalchemy.types import TypeDecorator from sqlalchemy.event import listens_for -from sqlalchemy import UniqueConstraint, Boolean, DateTime, Column, Integer, String, ForeignKey, Unicode, UnicodeText, Numeric, LargeBinary +from sqlalchemy import ( + UniqueConstraint, + Boolean, + DateTime, + Column, + Integer, + String, + ForeignKey, + Unicode, + UnicodeText, + Numeric, +) from sqlalchemy_utils import ColorType from flask_security import UserMixin, RoleMixin from flask_dance.consumer.storage.sqla import OAuthConsumerMixin @@ -15,23 +25,26 @@ from project.dbtypes import IntegerEnum from geoalchemy2 import Geometry from sqlalchemy import and_ -### Base +# Base + class TrackableMixin(object): created_at = Column(DateTime, default=datetime.datetime.utcnow) @declared_attr def created_by_id(cls): - return Column('created_by_id', ForeignKey('user.id')) + return Column("created_by_id", ForeignKey("user.id")) @declared_attr def created_by(cls): return relationship("User") -### Multi purpose + +# Multi purpose + class Image(db.Model, TrackableMixin): - __tablename__ = 'image' + __tablename__ = "image" id = Column(Integer(), primary_key=True) data = deferred(db.Column(db.LargeBinary)) encoding_format = Column(String(80)) @@ -40,24 +53,28 @@ class Image(db.Model, TrackableMixin): def is_empty(self): return not self.data -### User + +# User + class RolesUsers(db.Model): - __tablename__ = 'roles_users' + __tablename__ = "roles_users" id = Column(Integer(), primary_key=True) - user_id = Column('user_id', Integer(), ForeignKey('user.id')) - role_id = Column('role_id', Integer(), ForeignKey('role.id')) + user_id = Column("user_id", Integer(), ForeignKey("user.id")) + role_id = Column("role_id", Integer(), ForeignKey("role.id")) + class Role(db.Model, RoleMixin): - __tablename__ = 'role' + __tablename__ = "role" id = Column(Integer(), primary_key=True) name = Column(String(80), unique=True) title = Column(Unicode(255)) description = Column(String(255)) permissions = Column(UnicodeText()) + class User(db.Model, UserMixin): - __tablename__ = 'user' + __tablename__ = "user" id = Column(Integer, primary_key=True) email = Column(String(255), unique=True) username = Column(String(255)) @@ -70,63 +87,76 @@ class User(db.Model, UserMixin): active = Column(Boolean()) fs_uniquifier = Column(String(255)) confirmed_at = Column(DateTime()) - roles = relationship('Role', secondary='roles_users', - backref=backref('users', lazy='dynamic')) + roles = relationship( + "Role", secondary="roles_users", backref=backref("users", lazy="dynamic") + ) + class OAuth(OAuthConsumerMixin, db.Model): provider_user_id = Column(String(256), unique=True, nullable=False) - user_id = Column(Integer(), ForeignKey('user.id'), nullable=False) - user = db.relationship('User') + user_id = Column(Integer(), ForeignKey("user.id"), nullable=False) + user = db.relationship("User") + + +# Admin Unit -### Admin Unit class AdminUnitMemberRolesMembers(db.Model): - __tablename__ = 'adminunitmemberroles_members' + __tablename__ = "adminunitmemberroles_members" id = Column(Integer(), primary_key=True) - member_id = Column('member_id', Integer(), ForeignKey('adminunitmember.id')) - role_id = Column('role_id', Integer(), ForeignKey('adminunitmemberrole.id')) + member_id = Column("member_id", Integer(), ForeignKey("adminunitmember.id")) + role_id = Column("role_id", Integer(), ForeignKey("adminunitmemberrole.id")) + class AdminUnitMemberRole(db.Model, RoleMixin): - __tablename__ = 'adminunitmemberrole' + __tablename__ = "adminunitmemberrole" id = Column(Integer(), primary_key=True) name = Column(String(80), unique=True) title = Column(Unicode(255)) description = Column(String(255)) permissions = Column(UnicodeText()) + class AdminUnitMember(db.Model): - __tablename__ = 'adminunitmember' + __tablename__ = "adminunitmember" id = Column(Integer(), primary_key=True) - admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False) - user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) - user = db.relationship('User', backref=db.backref('adminunitmembers', lazy=True)) - roles = relationship('AdminUnitMemberRole', secondary='adminunitmemberroles_members', - order_by="AdminUnitMemberRole.id", - backref=backref('members', lazy='dynamic')) + admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) + user = db.relationship("User", backref=db.backref("adminunitmembers", lazy=True)) + roles = relationship( + "AdminUnitMemberRole", + secondary="adminunitmemberroles_members", + order_by="AdminUnitMemberRole.id", + backref=backref("members", lazy="dynamic"), + ) + class AdminUnitMemberInvitation(db.Model): - __tablename__ = 'adminunitmemberinvitation' - __table_args__ = ( - UniqueConstraint('email', 'admin_unit_id'), - ) + __tablename__ = "adminunitmemberinvitation" + __table_args__ = (UniqueConstraint("email", "admin_unit_id"),) id = Column(Integer(), primary_key=True) - admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False) + admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False) email = Column(String(255)) roles = Column(UnicodeText()) + class AdminUnit(db.Model, TrackableMixin): - __tablename__ = 'adminunit' + __tablename__ = "adminunit" id = Column(Integer(), primary_key=True) name = Column(Unicode(255), unique=True) short_name = Column(Unicode(100), unique=True) - members = relationship('AdminUnitMember', backref=backref('adminunit', lazy=True)) - invitations = relationship('AdminUnitMemberInvitation', backref=backref('adminunit', lazy=True)) - event_organizers = relationship('EventOrganizer', backref=backref('adminunit', lazy=True)) - event_places = relationship('EventPlace', backref=backref('adminunit', lazy=True)) - location_id = db.Column(db.Integer, db.ForeignKey('location.id')) - location = db.relationship('Location') - logo_id = db.Column(db.Integer, db.ForeignKey('image.id')) - logo = db.relationship('Image', uselist=False) + members = relationship("AdminUnitMember", backref=backref("adminunit", lazy=True)) + invitations = relationship( + "AdminUnitMemberInvitation", backref=backref("adminunit", lazy=True) + ) + event_organizers = relationship( + "EventOrganizer", backref=backref("adminunit", lazy=True) + ) + event_places = relationship("EventPlace", backref=backref("adminunit", lazy=True)) + location_id = db.Column(db.Integer, db.ForeignKey("location.id")) + location = db.relationship("Location") + logo_id = db.Column(db.Integer, db.ForeignKey("image.id")) + logo = db.relationship("Image", uselist=False) url = Column(String(255)) email = Column(Unicode(255)) phone = Column(Unicode(255)) @@ -136,95 +166,113 @@ class AdminUnit(db.Model, TrackableMixin): widget_primary_color = Column(ColorType) widget_link_color = Column(ColorType) -@listens_for(AdminUnit, 'before_insert') -@listens_for(AdminUnit, 'before_update') + +@listens_for(AdminUnit, "before_insert") +@listens_for(AdminUnit, "before_update") def purge_admin_unit(mapper, connect, self): if self.logo and self.logo.is_empty(): self.logo_id = None + # Universal Types + class Location(db.Model, TrackableMixin): - __tablename__ = 'location' + __tablename__ = "location" id = Column(Integer(), primary_key=True) street = Column(Unicode(255)) postalCode = Column(Unicode(255)) city = Column(Unicode(255)) state = Column(Unicode(255)) country = Column(Unicode(255)) - latitude = Column(Numeric(18,16)) - longitude = Column(Numeric(19,16)) + latitude = Column(Numeric(18, 16)) + longitude = Column(Numeric(19, 16)) coordinate = Column(Geometry(geometry_type="POINT")) def is_empty(self): - return (not self.street + return ( + not self.street and not self.postalCode and not self.city and not self.state and not self.country and not self.latitude - and not self.longitude) + and not self.longitude + ) def update_coordinate(self): if self.latitude and self.longitude: - point = 'POINT({} {})'.format(self.longitude, self.latitude) + point = "POINT({} {})".format(self.longitude, self.latitude) self.coordinate = point else: self.coordinate = None @classmethod def update_coordinates(cls): - locations = Location.query.filter(and_(Location.latitude != None, Location.latitude != 0, Location.coordinate == None)).all() + locations = Location.query.filter( + and_( + Location.latitude is not None, + Location.latitude != 0, + Location.coordinate is None, + ) + ).all() for location in locations: location.update_coordinate() db.session.commit() -@listens_for(Location, 'before_insert') -@listens_for(Location, 'before_update') + +@listens_for(Location, "before_insert") +@listens_for(Location, "before_update") def update_location_coordinate(mapper, connect, self): self.update_coordinate() + # Events class EventPlace(db.Model, TrackableMixin): - __tablename__ = 'eventplace' + __tablename__ = "eventplace" id = Column(Integer(), primary_key=True) name = Column(Unicode(255), nullable=False) - location_id = db.Column(db.Integer, db.ForeignKey('location.id')) - location = db.relationship('Location', uselist=False) - photo_id = db.Column(db.Integer, db.ForeignKey('image.id')) - photo = db.relationship('Image', uselist=False) + location_id = db.Column(db.Integer, db.ForeignKey("location.id")) + location = db.relationship("Location", uselist=False) + photo_id = db.Column(db.Integer, db.ForeignKey("image.id")) + photo = db.relationship("Image", uselist=False) url = Column(String(255)) description = Column(UnicodeText()) - admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=True) + admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=True) def is_empty(self): - return (not self.name) + return not self.name -@listens_for(EventPlace, 'before_insert') -@listens_for(EventPlace, 'before_update') + +@listens_for(EventPlace, "before_insert") +@listens_for(EventPlace, "before_update") def purge_event_place(mapper, connect, self): if self.location and self.location.is_empty(): self.location_id = None if self.photo and self.photo.is_empty(): self.photo_id = None + class EventCategory(db.Model): - __tablename__ = 'eventcategory' + __tablename__ = "eventcategory" id = Column(Integer(), primary_key=True) name = Column(Unicode(255), nullable=False, unique=True) + class EventTargetGroupOrigin(IntEnum): both = 1 tourist = 2 resident = 3 + class EventAttendanceMode(IntEnum): offline = 1 online = 2 mixed = 3 + class EventStatus(IntEnum): scheduled = 1 cancelled = 2 @@ -232,65 +280,77 @@ class EventStatus(IntEnum): postponed = 4 rescheduled = 5 + class EventReviewStatus(IntEnum): inbox = 1 verified = 2 rejected = 3 + class EventRejectionReason(IntEnum): duplicate = 1 untrustworthy = 2 illegal = 3 + class EventReferenceRequestReviewStatus(IntEnum): inbox = 1 verified = 2 rejected = 3 + class EventReferenceRequestRejectionReason(IntEnum): duplicate = 1 untrustworthy = 2 illegal = 3 irrelevant = 4 + class EventOrganizer(db.Model, TrackableMixin): - __tablename__ = 'eventorganizer' - __table_args__ = (UniqueConstraint('name', 'admin_unit_id'),) + __tablename__ = "eventorganizer" + __table_args__ = (UniqueConstraint("name", "admin_unit_id"),) id = Column(Integer(), primary_key=True) name = Column(Unicode(255), nullable=False) url = Column(String(255)) email = Column(Unicode(255)) phone = Column(Unicode(255)) fax = Column(Unicode(255)) - location_id = db.Column(db.Integer, db.ForeignKey('location.id')) - location = db.relationship('Location') - logo_id = db.Column(db.Integer, db.ForeignKey('image.id')) - logo = db.relationship('Image', uselist=False) - admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=True) + location_id = db.Column(db.Integer, db.ForeignKey("location.id")) + location = db.relationship("Location") + logo_id = db.Column(db.Integer, db.ForeignKey("image.id")) + logo = db.relationship("Image", uselist=False) + admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=True) def is_empty(self): return not self.name -@listens_for(EventOrganizer, 'before_insert') -@listens_for(EventOrganizer, 'before_update') + +@listens_for(EventOrganizer, "before_insert") +@listens_for(EventOrganizer, "before_update") def purge_event_organizer(mapper, connect, self): if self.logo and self.logo.is_empty(): self.logo_id = None + class EventReference(db.Model, TrackableMixin): - __tablename__ = 'eventreference' + __tablename__ = "eventreference" id = Column(Integer(), primary_key=True) - event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) - admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False) - admin_unit = db.relationship('AdminUnit', backref=db.backref('references', lazy=True)) + event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False) + admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False) + admin_unit = db.relationship( + "AdminUnit", backref=db.backref("references", lazy=True) + ) rating = Column(Integer()) + class EventReferenceRequest(db.Model, TrackableMixin): - __tablename__ = 'eventreferencerequest' + __tablename__ = "eventreferencerequest" id = Column(Integer(), primary_key=True) - event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) - admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False) - admin_unit = db.relationship('AdminUnit', backref=db.backref('reference_requests', lazy=True)) + event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False) + admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False) + admin_unit = db.relationship( + "AdminUnit", backref=db.backref("reference_requests", lazy=True) + ) review_status = Column(IntegerEnum(EventReferenceRequestReviewStatus)) rejection_reason = Column(IntegerEnum(EventReferenceRequestRejectionReason)) @@ -298,12 +358,13 @@ class EventReferenceRequest(db.Model, TrackableMixin): def verified(self): return self.review_status == EventReferenceRequestReviewStatus.verified + class EventSuggestion(db.Model, TrackableMixin): - __tablename__ = 'eventsuggestion' + __tablename__ = "eventsuggestion" __table_args__ = ( - CheckConstraint('NOT(event_place_id IS NULL AND event_place_text IS NULL)'), - CheckConstraint('NOT(organizer_id IS NULL AND organizer_text IS NULL)'), - ) + CheckConstraint("NOT(event_place_id IS NULL AND event_place_text IS NULL)"), + CheckConstraint("NOT(organizer_id IS NULL AND organizer_text IS NULL)"), + ) id = Column(Integer(), primary_key=True) name = Column(Unicode(255), nullable=False) @@ -318,29 +379,38 @@ class EventSuggestion(db.Model, TrackableMixin): contact_phone = Column(Unicode(255)) contact_email_notice = Column(Boolean()) - admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False) - admin_unit = db.relationship('AdminUnit', backref=db.backref('eventsuggestions', lazy=True)) + admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False) + admin_unit = db.relationship( + "AdminUnit", backref=db.backref("eventsuggestions", lazy=True) + ) - event_place_id = db.Column(db.Integer, db.ForeignKey('eventplace.id'), nullable=True) - event_place = db.relationship('EventPlace', uselist=False) + event_place_id = db.Column( + db.Integer, db.ForeignKey("eventplace.id"), nullable=True + ) + event_place = db.relationship("EventPlace", uselist=False) event_place_text = Column(Unicode(255), nullable=True) - organizer_id = db.Column(db.Integer, db.ForeignKey('eventorganizer.id'), nullable=True) - organizer = db.relationship('EventOrganizer', uselist=False) + organizer_id = db.Column( + db.Integer, db.ForeignKey("eventorganizer.id"), nullable=True + ) + organizer = db.relationship("EventOrganizer", uselist=False) organizer_text = Column(Unicode(255), nullable=True) - photo_id = db.Column(db.Integer, db.ForeignKey('image.id')) - photo = db.relationship('Image', uselist=False) + photo_id = db.Column(db.Integer, db.ForeignKey("image.id")) + photo = db.relationship("Image", uselist=False) - event_id = db.Column(db.Integer, db.ForeignKey('event.id', ondelete='SET NULL'), nullable=True) - event = db.relationship('Event', uselist=False) + event_id = db.Column( + db.Integer, db.ForeignKey("event.id", ondelete="SET NULL"), nullable=True + ) + event = db.relationship("Event", uselist=False) @hybrid_property def verified(self): return self.review_status == EventReviewStatus.verified -@listens_for(EventSuggestion, 'before_insert') -@listens_for(EventSuggestion, 'before_update') + +@listens_for(EventSuggestion, "before_insert") +@listens_for(EventSuggestion, "before_update") def purge_event_suggestion(mapper, connect, self): if self.organizer and self.organizer.is_empty(): self.organizer_id = None @@ -353,23 +423,28 @@ def purge_event_suggestion(mapper, connect, self): if self.photo and self.photo.is_empty(): self.photo_id = None + class Event(db.Model, TrackableMixin): - __tablename__ = 'event' + __tablename__ = "event" id = Column(Integer(), primary_key=True) - admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False) - admin_unit = db.relationship('AdminUnit', backref=db.backref('events', lazy=True)) - organizer_id = db.Column(db.Integer, db.ForeignKey('eventorganizer.id'), nullable=True) - organizer = db.relationship('EventOrganizer', uselist=False) - event_place_id = db.Column(db.Integer, db.ForeignKey('eventplace.id'), nullable=True) - event_place = db.relationship('EventPlace', uselist=False) + admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False) + admin_unit = db.relationship("AdminUnit", backref=db.backref("events", lazy=True)) + organizer_id = db.Column( + db.Integer, db.ForeignKey("eventorganizer.id"), nullable=True + ) + organizer = db.relationship("EventOrganizer", uselist=False) + event_place_id = db.Column( + db.Integer, db.ForeignKey("eventplace.id"), nullable=True + ) + event_place = db.relationship("EventPlace", uselist=False) name = Column(Unicode(255), nullable=False) description = Column(UnicodeText(), nullable=False) external_link = Column(String(255)) ticket_link = Column(String(255)) - photo_id = db.Column(db.Integer, db.ForeignKey('image.id')) - photo = db.relationship('Image', uselist=False) - categories = relationship('EventCategory', secondary='event_eventcategories') + photo_id = db.Column(db.Integer, db.ForeignKey("image.id")) + photo = db.relationship("Image", uselist=False) + categories = relationship("EventCategory", secondary="event_eventcategories") tags = Column(UnicodeText()) kid_friendly = Column(Boolean()) accessible_for_free = Column(Boolean()) @@ -389,10 +464,20 @@ class Event(db.Model, TrackableMixin): recurrence_rule = Column(UnicodeText()) start = db.Column(db.DateTime(timezone=True), nullable=True) end = db.Column(db.DateTime(timezone=True), nullable=True) - dates = relationship('EventDate', backref=backref('event', lazy=False), cascade="all, delete-orphan") + dates = relationship( + "EventDate", backref=backref("event", lazy=False), cascade="all, delete-orphan" + ) - references = relationship('EventReference', backref=backref('event', lazy=False), cascade="all, delete-orphan") - reference_requests = relationship('EventReferenceRequest', backref=backref('event', lazy=False), cascade="all, delete-orphan") + references = relationship( + "EventReference", + backref=backref("event", lazy=False), + cascade="all, delete-orphan", + ) + reference_requests = relationship( + "EventReferenceRequest", + backref=backref("event", lazy=False), + cascade="all, delete-orphan", + ) @hybrid_property def category(self): @@ -401,8 +486,9 @@ class Event(db.Model, TrackableMixin): else: return None -@listens_for(Event, 'before_insert') -@listens_for(Event, 'before_update') + +@listens_for(Event, "before_insert") +@listens_for(Event, "before_update") def purge_event(mapper, connect, self): if self.organizer and self.organizer.is_empty(): self.organizer_id = None @@ -411,36 +497,45 @@ def purge_event(mapper, connect, self): if self.photo and self.photo.is_empty(): self.photo_id = None + class EventDate(db.Model): - __tablename__ = 'eventdate' + __tablename__ = "eventdate" id = Column(Integer(), primary_key=True) - event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) + event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False) start = db.Column(db.DateTime(timezone=True), nullable=False) end = db.Column(db.DateTime(timezone=True), nullable=True) + class EventEventCategories(db.Model): - __tablename__ = 'event_eventcategories' + __tablename__ = "event_eventcategories" id = Column(Integer(), primary_key=True) - event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) - category_id = db.Column(db.Integer, db.ForeignKey('eventcategory.id'), nullable=False) + event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False) + category_id = db.Column( + db.Integer, db.ForeignKey("eventcategory.id"), nullable=False + ) + class Analytics(db.Model): - __tablename__ = 'analytics' + __tablename__ = "analytics" id = Column(Integer(), primary_key=True) key = Column(Unicode(255)) value1 = Column(Unicode(255)) value2 = Column(Unicode(255)) created_at = Column(DateTime, default=datetime.datetime.utcnow) + # Deprecated begin class FeaturedEventReviewStatus(IntEnum): inbox = 1 verified = 2 rejected = 3 + class FeaturedEventRejectionReason(IntEnum): duplicate = 1 untrustworthy = 2 illegal = 3 irrelevant = 4 + + # Deprecated end diff --git a/project/oauth.py b/project/oauth.py index 046a52a..a5377dd 100644 --- a/project/oauth.py +++ b/project/oauth.py @@ -3,8 +3,7 @@ from flask_security import current_user, login_user from flask_dance.contrib.google import make_google_blueprint from flask_dance.consumer import oauth_authorized, oauth_error from flask_dance.consumer.storage.sqla import SQLAlchemyStorage -from sqlalchemy.orm.exc import NoResultFound -from project.models import User, OAuth +from project.models import OAuth from project import db, user_datastore from flask_babelex import gettext @@ -31,14 +30,16 @@ def google_logged_in(blueprint, token): user_id = info["id"] # Find this OAuth token in the database, or create it - oauth = OAuth.query.filter_by(provider=blueprint.name, provider_user_id=user_id).first() + oauth = OAuth.query.filter_by( + provider=blueprint.name, provider_user_id=user_id + ).first() if oauth is None: oauth = OAuth(provider=blueprint.name, provider_user_id=user_id, token=token) if oauth.user: login_user(oauth.user, authn_via=["google"]) user_datastore.commit() - flash(gettext("Successfully signed in."), 'success') + flash(gettext("Successfully signed in."), "success") else: # Create a new local user account for this user @@ -51,7 +52,7 @@ def google_logged_in(blueprint, token): # Log in the new local user account login_user(user, authn_via=["google"]) user_datastore.commit() - flash(gettext("Successfully signed in."), 'success') + flash(gettext("Successfully signed in."), "success") # Disable Flask-Dance's default behavior for saving the OAuth token return False diff --git a/project/scrape/scrape_fp.py b/project/scrape/scrape_fp.py index a859e27..5e1bb60 100644 --- a/project/scrape/scrape_fp.py +++ b/project/scrape/scrape_fp.py @@ -1,23 +1,34 @@ -from project import app, db, get_admin_unit, update_event_dates_with_recurrence_rule, upsert_event_category +from project import ( + db, + get_admin_unit, + update_event_dates_with_recurrence_rule, + upsert_event_category, +) from pprint import pprint import datetime -from dateutil import parser, tz import pytz -from urllib.request import urlopen, URLError +from urllib.request import urlopen from bs4 import BeautifulSoup -import requests from os import path import json import re -import unicodedata import decimal -from project.models import EventReviewStatus, EventTargetGroupOrigin, Location, Event, EventStatus, EventCategory, EventPlace, EventOrganizer, AdminUnit -from sqlalchemy import and_, or_, not_ +from project.models import ( + EventReviewStatus, + EventTargetGroupOrigin, + Location, + Event, + EventStatus, + EventPlace, + EventOrganizer, +) +from sqlalchemy import and_ + +berlin_tz = pytz.timezone("Europe/Berlin") -berlin_tz = pytz.timezone('Europe/Berlin') def scrape(debug): - url = 'https://goslar.feripro.de/programm/42/anmeldung/veranstaltungen' + url = "https://goslar.feripro.de/programm/42/anmeldung/veranstaltungen" if debug: filename = "tmp/fp.html" @@ -27,51 +38,61 @@ def scrape(debug): with open(filename, "wb") as text_file: text_file.write(response.read()) - doc = BeautifulSoup(open(filename), 'html.parser') + doc = BeautifulSoup(open(filename), "html.parser") else: response = urlopen(url) - doc = BeautifulSoup(response, 'html.parser') + doc = BeautifulSoup(response, "html.parser") js_assigns_regex = r"(\w*)\s*:\s*JSON\.parse\('(.*)'\)" js_assigns = dict() - javascripts = doc.find_all('script') + javascripts = doc.find_all("script") for javascript in javascripts: - javascript_contents = javascript.contents[0] if len(javascript.contents) > 0 else '' + javascript_contents = ( + javascript.contents[0] if len(javascript.contents) > 0 else "" + ) - if 'window.fp_initial' in javascript_contents: + if "window.fp_initial" in javascript_contents: matches = re.findall(js_assigns_regex, javascript_contents, re.MULTILINE) for match in matches: key = match[0] - if not key in ['events']: + if key not in ["events"]: continue json_str = match[1] - decoded_json_str = json_str.encode('utf-8').decode('unicode_escape').encode('latin-1').decode('utf-8') + decoded_json_str = ( + json_str.encode("utf-8") + .decode("unicode_escape") + .encode("latin-1") + .decode("utf-8") + ) value = json.loads(decoded_json_str, strict=False) js_assigns[key] = value break - admin_unit = get_admin_unit('Ferienpass Goslar') - category = upsert_event_category('Other') + admin_unit = get_admin_unit("Ferienpass Goslar") + category = upsert_event_category("Other") - for js_event in js_assigns['events']: - if not 'event_id' in js_event: + for js_event in js_assigns["events"]: + if "event_id" not in js_event: continue - event_id = js_event['event_id'] + event_id = js_event["event_id"] if not event_id: continue try: - external_link = url + '#' + str(event_id) + external_link = url + "#" + str(event_id) event = Event.query.filter(Event.external_link == external_link).first() did_create = False # Event if event is None: - if js_event['name'] in ['Entfällt', 'Diese Veranstaltung muss leider ausfallen ...']: + if js_event["name"] in [ + "Entfällt", + "Diese Veranstaltung muss leider ausfallen ...", + ]: continue event = Event() @@ -83,27 +104,46 @@ def scrape(debug): event.review_status = EventReviewStatus.verified event.rating = 5 event.target_group_origin = EventTargetGroupOrigin.resident - event.name = js_event['name'] - event.description = js_event['description'] - start = parse_date_time_str(js_event['start']) - end = parse_date_time_str(js_event['end']) + event.name = js_event["name"] + event.description = js_event["description"] + start = parse_date_time_str(js_event["start"]) + end = parse_date_time_str(js_event["end"]) update_event_dates_with_recurrence_rule(event, start, end) # Organizer - js_organizer = js_event['organizer'] - organizer_name = js_event['name_public'] if js_event['name_public'] else js_organizer['name'] - organizer_phone = js_event['phone_public'] if js_event['phone_public'] else js_organizer['phone'] - organizer_email = js_event['email_public'] if js_event['email_public'] else js_organizer['email'] - organizer_url = js_organizer['website'] if js_organizer['website'] else js_organizer['facebook'] + js_organizer = js_event["organizer"] + organizer_name = ( + js_event["name_public"] + if js_event["name_public"] + else js_organizer["name"] + ) + organizer_phone = ( + js_event["phone_public"] + if js_event["phone_public"] + else js_organizer["phone"] + ) + organizer_email = ( + js_event["email_public"] + if js_event["email_public"] + else js_organizer["email"] + ) + organizer_url = ( + js_organizer["website"] + if js_organizer["website"] + else js_organizer["facebook"] + ) - organizer = EventOrganizer.query.filter(and_( - EventOrganizer.admin_unit_id == admin_unit.id, - EventOrganizer.name == organizer_name)).first() + organizer = EventOrganizer.query.filter( + and_( + EventOrganizer.admin_unit_id == admin_unit.id, + EventOrganizer.name == organizer_name, + ) + ).first() if organizer is None: organizer = EventOrganizer( - admin_unit_id = admin_unit.id, - name = organizer_name) + admin_unit_id=admin_unit.id, name=organizer_name + ) organizer.phone = organizer_phone organizer.email = organizer_email @@ -115,16 +155,19 @@ def scrape(debug): place_description = "" place_location = None - meeting_point = js_event['meeting_point'].replace('\r\n', ', ') + meeting_point = js_event["meeting_point"].replace("\r\n", ", ") if len(meeting_point) > 80: - place_name = meeting_point[:80] + '...' + place_name = meeting_point[:80] + "..." place_description = meeting_point else: place_name = meeting_point - if 'meeting_point_latitude' in js_event and 'meeting_point_longitude' in js_event: - meeting_point_latitude = js_event['meeting_point_latitude'] - meeting_point_longitude = js_event['meeting_point_longitude'] + if ( + "meeting_point_latitude" in js_event + and "meeting_point_longitude" in js_event + ): + meeting_point_latitude = js_event["meeting_point_latitude"] + meeting_point_longitude = js_event["meeting_point_longitude"] if meeting_point_latitude and meeting_point_longitude: latitude = decimal.Decimal(meeting_point_latitude) longitude = decimal.Decimal(meeting_point_longitude) @@ -133,45 +176,55 @@ def scrape(debug): place_location.latitude = latitude place_location.longitude = longitude - place = EventPlace.query.filter(and_( - EventPlace.admin_unit_id == admin_unit.id, - EventPlace.organizer_id == organizer.id, - EventPlace.name == place_name)).first() + place = EventPlace.query.filter( + and_( + EventPlace.admin_unit_id == admin_unit.id, + EventPlace.organizer_id == organizer.id, + EventPlace.name == place_name, + ) + ).first() if place is None: place = EventPlace( - admin_unit_id = admin_unit.id, - organizer_id = organizer.id, - name = place_name) + admin_unit_id=admin_unit.id, + organizer_id=organizer.id, + name=place_name, + ) place.description = place_description place.location = place_location event.event_place = place # Additional data - event.status = EventStatus.cancelled if js_event['canceled'] else EventStatus.scheduled + event.status = ( + EventStatus.cancelled if js_event["canceled"] else EventStatus.scheduled + ) event.kid_friendly = True - event.accessible_for_free = js_event['price'] == '0.00' + event.accessible_for_free = js_event["price"] == "0.00" - tag_list = js_event['tags'] - tag_list.append('Ferienpass') - event.tags = ','.join(tag_list) + tag_list = js_event["tags"] + tag_list.append("Ferienpass") + event.tags = ",".join(tag_list) - if js_event['min_age']: - event.age_from = int(js_event['min_age']) + if js_event["min_age"]: + event.age_from = int(js_event["min_age"]) - if js_event['max_age']: - event.age_to = int(js_event['max_age']) + if js_event["max_age"]: + event.age_to = int(js_event["max_age"]) - print("%s %s %s %s" % (event.dates[0].start, event.name, organizer.id, organizer.name)) + print( + "%s %s %s %s" + % (event.dates[0].start, event.name, organizer.id, organizer.name) + ) if did_create: db.session.add(event) db.session.commit() - except: + except Exception: print("Exception") pprint(js_event) + def parse_date_time_str(date_time_str): if not date_time_str: return None @@ -179,5 +232,6 @@ def parse_date_time_str(date_time_str): date_time = datetime.datetime.fromisoformat(date_time_str) return berlin_tz.localize(date_time) -if __name__ == '__main__': + +if __name__ == "__main__": scrape(False) diff --git a/project/scrape/scrape_hi.py b/project/scrape/scrape_hi.py index 0257a50..ec58203 100644 --- a/project/scrape/scrape_hi.py +++ b/project/scrape/scrape_hi.py @@ -1,45 +1,50 @@ -from project import app, db +from project import db from pprint import pprint import datetime -from dateutil import parser, tz -import pytz -from urllib import request, parse -from urllib.request import urlopen, URLError -from bs4 import BeautifulSoup -import requests +from urllib import request from os import path import json -from flask import jsonify -import re -import unicodedata import decimal -from project.models import EventReviewStatus, EventTargetGroupOrigin, Location, Event, EventStatus, EventCategory, EventPlace, EventOrganizer, AdminUnit -from sqlalchemy import and_, or_, not_ -from project.dateutils import berlin_tz +from project.models import ( + EventReviewStatus, + Location, + Event, + EventStatus, + EventPlace, + EventOrganizer, +) +from sqlalchemy import and_, not_ from project.services.admin_unit import get_admin_unit -from project.services.event import upsert_event_category, update_event_dates_with_recurrence_rule +from project.services.event import ( + upsert_event_category, + update_event_dates_with_recurrence_rule, +) -admin_unit = get_admin_unit('Harzinfo') -category = upsert_event_category('Other') +admin_unit = get_admin_unit("Harzinfo") +category = upsert_event_category("Other") base_url = "https://www.harzinfo.de" url = base_url + "/?ndssearch=fullsearch&no_cache=1&L=0" -with open('scrape_hi_req.json') as json_file: +with open("scrape_hi_req.json") as json_file: request_object = json.load(json_file) -with open('scrape_hi_cities.json') as json_file: +with open("scrape_hi_cities.json") as json_file: cities = json.load(json_file) + def response_from_url(city): body = request_object - body["searchFilter"]["ndsdestinationdataevent"]["city"] = { str(city['id']): city['short_name'] or city['title'] } - req = request.Request(url, data=bytes(json.dumps(body), encoding='utf-8')) - req.add_header('Content-Type', 'application/json') + body["searchFilter"]["ndsdestinationdataevent"]["city"] = { + str(city["id"]): city["short_name"] or city["title"] + } + req = request.Request(url, data=bytes(json.dumps(body), encoding="utf-8")) + req.add_header("Content-Type", "application/json") return request.urlopen(req) + def load_json(debug, city): if debug: - filename = "tmp/hi_%d.html" % (city['id']) + filename = "tmp/hi_%d.html" % (city["id"]) if not path.exists(filename): response = response_from_url(city) @@ -52,24 +57,27 @@ def load_json(debug, city): response = response_from_url(city) return json.load(response) + def parse_date_time_str(date_time_str): if not date_time_str: return None - return datetime.datetime.fromisoformat(date_time_str + ':00') + return datetime.datetime.fromisoformat(date_time_str + ":00") + def scrape(debug, city): # Organizer - organizer_name = city['short_name'] or city['title'] - organizer = EventOrganizer.query.filter(and_( - EventOrganizer.admin_unit_id == admin_unit.id, - EventOrganizer.name == organizer_name)).first() + organizer_name = city["short_name"] or city["title"] + organizer = EventOrganizer.query.filter( + and_( + EventOrganizer.admin_unit_id == admin_unit.id, + EventOrganizer.name == organizer_name, + ) + ).first() if organizer is None: - organizer = EventOrganizer( - admin_unit_id = admin_unit.id, - name = organizer_name) + organizer = EventOrganizer(admin_unit_id=admin_unit.id, name=organizer_name) db.session.add(organizer) db.session.commit() @@ -81,8 +89,13 @@ def scrape(debug, city): for item in result: try: uid = str(item["uid"]) - external_link = base_url + item["link"] + '#' + uid - event = Event.query.filter(and_(Event.organizer_id == organizer.id, Event.external_link == external_link)).first() + external_link = base_url + item["link"] + "#" + uid + event = Event.query.filter( + and_( + Event.organizer_id == organizer.id, + Event.external_link == external_link, + ) + ).first() did_create = False if event is None: @@ -100,7 +113,7 @@ def scrape(debug, city): event.name = item["title"] event.description = item["title"] - start = parse_date_time_str(item['date']) + start = parse_date_time_str(item["date"]) update_event_dates_with_recurrence_rule(event, start, None) # Place @@ -108,9 +121,9 @@ def scrape(debug, city): place_description = "" place_location = None - if 'latitude' in item and 'longitude' in item: - meeting_point_latitude = item['latitude'] - meeting_point_longitude = item['longitude'] + if "latitude" in item and "longitude" in item: + meeting_point_latitude = item["latitude"] + meeting_point_longitude = item["longitude"] if meeting_point_latitude and meeting_point_longitude: latitude = decimal.Decimal(meeting_point_latitude) longitude = decimal.Decimal(meeting_point_longitude) @@ -119,74 +132,87 @@ def scrape(debug, city): place_location.latitude = latitude place_location.longitude = longitude - place = EventPlace.query.filter(and_( - EventPlace.admin_unit_id == admin_unit.id, - EventPlace.organizer_id == organizer.id, - EventPlace.name == place_name)).first() + place = EventPlace.query.filter( + and_( + EventPlace.admin_unit_id == admin_unit.id, + EventPlace.organizer_id == organizer.id, + EventPlace.name == place_name, + ) + ).first() if place is None: place = EventPlace( - admin_unit_id = admin_unit.id, - organizer_id = organizer.id, - name = place_name) + admin_unit_id=admin_unit.id, + organizer_id=organizer.id, + name=place_name, + ) place.description = place_description place.location = place_location event.event_place = place # Additional data - event.status = EventStatus.cancelled if item['canceled'] else EventStatus.scheduled + event.status = ( + EventStatus.cancelled if item["canceled"] else EventStatus.scheduled + ) - if 'categories' in item: - tag_list = list(item['categories'].values()) + if "categories" in item: + tag_list = list(item["categories"].values()) - if 'Ausstellung/Kunst' in tag_list: - event.category = upsert_event_category('Art') - elif 'Comedy' in tag_list: - event.category = upsert_event_category('Comedy') - elif 'Konzert/Musik' in tag_list: - event.category = upsert_event_category('Music') - elif 'Theater' in tag_list: - event.category = upsert_event_category('Theater') - elif 'Genuss/Gourmet' in tag_list: - event.category = upsert_event_category('Dining') - elif 'Gesundheit/Wellness' in tag_list: - event.category = upsert_event_category('Fitness') - elif 'Kinder/Jugend' in tag_list: - event.category = upsert_event_category('Family') - elif 'Markt/Flohmarkt' in tag_list: - event.category = upsert_event_category('Shopping') - elif 'Sport' in tag_list: - event.category = upsert_event_category('Sports') - elif 'Vortrag/Lesung' in tag_list: - event.category = upsert_event_category('Book') - elif 'Kabarett' in tag_list: - event.category = upsert_event_category('Art') - elif 'Musical' in tag_list: - event.category = upsert_event_category('Theater') - elif 'Weihnachtsmärkte' in tag_list: - event.category = upsert_event_category('Festival') - elif 'Stadt- und Volksfeste' in tag_list: - event.category = upsert_event_category('Festival') + if "Ausstellung/Kunst" in tag_list: + event.category = upsert_event_category("Art") + elif "Comedy" in tag_list: + event.category = upsert_event_category("Comedy") + elif "Konzert/Musik" in tag_list: + event.category = upsert_event_category("Music") + elif "Theater" in tag_list: + event.category = upsert_event_category("Theater") + elif "Genuss/Gourmet" in tag_list: + event.category = upsert_event_category("Dining") + elif "Gesundheit/Wellness" in tag_list: + event.category = upsert_event_category("Fitness") + elif "Kinder/Jugend" in tag_list: + event.category = upsert_event_category("Family") + elif "Markt/Flohmarkt" in tag_list: + event.category = upsert_event_category("Shopping") + elif "Sport" in tag_list: + event.category = upsert_event_category("Sports") + elif "Vortrag/Lesung" in tag_list: + event.category = upsert_event_category("Book") + elif "Kabarett" in tag_list: + event.category = upsert_event_category("Art") + elif "Musical" in tag_list: + event.category = upsert_event_category("Theater") + elif "Weihnachtsmärkte" in tag_list: + event.category = upsert_event_category("Festival") + elif "Stadt- und Volksfeste" in tag_list: + event.category = upsert_event_category("Festival") - if 'Kinder/Jugend' in tag_list: + if "Kinder/Jugend" in tag_list: event.kid_friendly = True - tag_list.append('Harzinfo') - event.tags = ','.join(tag_list) + tag_list.append("Harzinfo") + event.tags = ",".join(tag_list) print("%s %s %d" % (event.dates[0].start, event.name, event.rating)) if did_create: db.session.add(event) db.session.commit() - except: + except Exception: print("Exception") pprint(item) - Event.query.filter(and_(Event.admin_unit_id == admin_unit.id, Event.organizer_id == organizer.id, not_(Event.id.in_(event_ids)))).delete(synchronize_session='fetch') + Event.query.filter( + and_( + Event.admin_unit_id == admin_unit.id, + Event.organizer_id == organizer.id, + not_(Event.id.in_(event_ids)), + ) + ).delete(synchronize_session="fetch") db.session.commit() -if __name__ == '__main__': + +if __name__ == "__main__": for city in cities.values(): scrape(False, city) diff --git a/project/services/admin_unit.py b/project/services/admin_unit.py index ad1c88d..874be7d 100644 --- a/project/services/admin_unit.py +++ b/project/services/admin_unit.py @@ -1,26 +1,29 @@ from project import db from project.models import AdminUnit, AdminUnitMember, AdminUnitMemberRole -def upsert_admin_unit(unit_name, short_name = None): - admin_unit = AdminUnit.query.filter_by(name = unit_name).first() + +def upsert_admin_unit(unit_name, short_name=None): + admin_unit = AdminUnit.query.filter_by(name=unit_name).first() if admin_unit is None: - admin_unit = AdminUnit(name = unit_name) + admin_unit = AdminUnit(name=unit_name) db.session.add(admin_unit) admin_unit.short_name = short_name - upsert_org_or_admin_unit_for_admin_unit(admin_unit) return admin_unit + def get_admin_unit(unit_name): - return AdminUnit.query.filter_by(name = unit_name).first() + return AdminUnit.query.filter_by(name=unit_name).first() + def get_admin_unit_member_role(role_name): - return AdminUnitMemberRole.query.filter_by(name = role_name).first() + return AdminUnitMemberRole.query.filter_by(name=role_name).first() + def upsert_admin_unit_member_role(role_name, role_title, permissions): - result = AdminUnitMemberRole.query.filter_by(name = role_name).first() + result = AdminUnitMemberRole.query.filter_by(name=role_name).first() if result is None: - result = AdminUnitMemberRole(name = role_name) + result = AdminUnitMemberRole(name=role_name) db.session.add(result) result.title = role_title @@ -28,25 +31,36 @@ def upsert_admin_unit_member_role(role_name, role_title, permissions): result.add_permissions(permissions) return result + def add_user_to_admin_unit(user, admin_unit): - result = AdminUnitMember.query.with_parent(admin_unit).filter_by(user_id = user.id).first() + result = ( + AdminUnitMember.query.with_parent(admin_unit).filter_by(user_id=user.id).first() + ) if result is None: - result = AdminUnitMember(user = user, admin_unit_id=admin_unit.id) + result = AdminUnitMember(user=user, admin_unit_id=admin_unit.id) admin_unit.members.append(result) db.session.add(result) return result + def add_user_to_admin_unit_with_roles(user, admin_unit, role_names): member = add_user_to_admin_unit(user, admin_unit) add_roles_to_admin_unit_member(member, role_names) return member + def add_roles_to_admin_unit_member(member, role_names): for role_name in role_names: role = get_admin_unit_member_role(role_name) add_role_to_admin_unit_member(member, role) + def add_role_to_admin_unit_member(admin_unit_member, role): - if AdminUnitMemberRole.query.with_parent(admin_unit_member).filter_by(name = role.name).first() is None: + if ( + AdminUnitMemberRole.query.with_parent(admin_unit_member) + .filter_by(name=role.name) + .first() + is None + ): admin_unit_member.roles.append(role) diff --git a/project/services/event.py b/project/services/event.py index 65b4d77..f956d0b 100644 --- a/project/services/event.py +++ b/project/services/event.py @@ -1,49 +1,84 @@ -from project.models import EventReviewStatus, EventCategory, Event, EventDate, EventReference, EventPlace, Location, EventSuggestion -from project.dateutils import dates_from_recurrence_rule, today, date_add_time, date_set_end_of_day -from sqlalchemy import and_, or_, not_, func +from project import db +from project.models import ( + EventCategory, + Event, + EventDate, + EventReference, + EventPlace, + Location, +) +from project.dateutils import ( + dates_from_recurrence_rule, + today, + date_add_time, +) +from sqlalchemy import and_, or_, func from sqlalchemy.sql import extract from dateutil.relativedelta import relativedelta + def upsert_event_category(category_name): - result = EventCategory.query.filter_by(name = category_name).first() + result = EventCategory.query.filter_by(name=category_name).first() if result is None: - result = EventCategory(name = category_name) + result = EventCategory(name=category_name) db.session.add(result) return result + def fill_event_filter(event_filter, params): if params.keyword: - like_keyword = '%' + params.keyword + '%' - event_filter = and_(event_filter, or_(Event.name.ilike(like_keyword), Event.description.ilike(like_keyword), Event.tags.ilike(like_keyword))) + like_keyword = "%" + params.keyword + "%" + event_filter = and_( + event_filter, + or_( + Event.name.ilike(like_keyword), + Event.description.ilike(like_keyword), + Event.tags.ilike(like_keyword), + ), + ) if params.category_id: if type(params.category_id) is list: category_ids = params.category_id else: category_ids = [params.category_id] - event_filter = and_(event_filter, Event.categories.any(EventCategory.id.in_(category_ids))) + event_filter = and_( + event_filter, Event.categories.any(EventCategory.id.in_(category_ids)) + ) if params.organizer_id: event_filter = and_(event_filter, Event.organizer_id == params.organizer_id) if params.latitude and params.longitude and params.distance: - point = 'POINT({} {})'.format(params.longitude, params.latitude) - event_filter = and_(event_filter, func.ST_DistanceSphere(Location.coordinate, point) <= params.distance) + point = "POINT({} {})".format(params.longitude, params.latitude) + event_filter = and_( + event_filter, + func.ST_DistanceSphere(Location.coordinate, point) <= params.distance, + ) return event_filter + def get_event_dates_query(params): - event_filter = (1 == 1) - date_filter = (EventDate.start >= today) + event_filter = 1 == 1 + date_filter = EventDate.start >= today event_filter = fill_event_filter(event_filter, params) if params.admin_unit_id: - event_filter = and_(event_filter, or_(Event.admin_unit_id == params.admin_unit_id, Event.references.any(EventReference.admin_unit_id == params.admin_unit_id))) + event_filter = and_( + event_filter, + or_( + Event.admin_unit_id == params.admin_unit_id, + Event.references.any( + EventReference.admin_unit_id == params.admin_unit_id + ), + ), + ) if params.date_from: - date_filter = (EventDate.start >= params.date_from) + date_filter = EventDate.start >= params.date_from if params.date_to: date_filter = and_(date_filter, EventDate.start < params.date_to) @@ -54,13 +89,21 @@ def get_event_dates_query(params): weekdays = params.weekday else: weekdays = [params.weekday] - date_filter = and_(date_filter, extract('dow', EventDate.start).in_(weekdays)) + date_filter = and_(date_filter, extract("dow", EventDate.start).in_(weekdays)) + + return ( + EventDate.query.join(Event) + .join(EventPlace, isouter=True) + .join(Location, isouter=True) + .filter(date_filter) + .filter(event_filter) + .order_by(EventDate.start) + ) - return EventDate.query.join(Event).join(EventPlace, isouter=True).join(Location, isouter=True).filter(date_filter).filter(event_filter).order_by(EventDate.start) def get_events_query(params): - event_filter = (1 == 1) - date_filter = (EventDate.start >= today) + event_filter = 1 == 1 + date_filter = EventDate.start >= today event_filter = fill_event_filter(event_filter, params) @@ -68,13 +111,19 @@ def get_events_query(params): event_filter = and_(event_filter, Event.admin_unit_id == params.admin_unit_id) if params.date_from: - date_filter = (EventDate.start >= params.date_from) + date_filter = EventDate.start >= params.date_from if params.date_to: date_filter = and_(date_filter, EventDate.start < params.date_to) event_filter = and_(event_filter, Event.dates.any(date_filter)) - return Event.query.join(EventPlace, isouter=True).join(Location, isouter=True).filter(event_filter).order_by(Event.start) + return ( + Event.query.join(EventPlace, isouter=True) + .join(Location, isouter=True) + .filter(event_filter) + .order_by(Event.start) + ) + def update_event_dates_with_recurrence_rule(event, start, end): event.start = start @@ -92,19 +141,30 @@ def update_event_dates_with_recurrence_rule(event, start, end): rr_dates = [start] for rr_date in rr_dates: - rr_date_start = date_add_time(rr_date, start.hour, start.minute, start.second, rr_date.tzinfo) + rr_date_start = date_add_time( + rr_date, start.hour, start.minute, start.second, rr_date.tzinfo + ) if end: rr_date_end = rr_date_start + time_difference else: rr_date_end = None - existing_date = next((date for date in event.dates if date.start == rr_date_start and date.end == rr_date_end), None) + existing_date = next( + ( + date + for date in event.dates + if date.start == rr_date_start and date.end == rr_date_end + ), + None, + ) if existing_date: dates_to_remove.remove(existing_date) else: - new_date = EventDate(event_id = event.id, start=rr_date_start, end=rr_date_end) + new_date = EventDate( + event_id=event.id, start=rr_date_start, end=rr_date_end + ) dates_to_add.append(new_date) event.dates = [date for date in event.dates if date not in dates_to_remove] - event.dates.extend(dates_to_add) \ No newline at end of file + event.dates.extend(dates_to_add) diff --git a/project/services/event_search.py b/project/services/event_search.py index 8b58cdc..d5afca4 100644 --- a/project/services/event_search.py +++ b/project/services/event_search.py @@ -1,9 +1,14 @@ -from project.dateutils import today, date_add_time, date_set_end_of_day, form_input_from_date, form_input_to_date +from project.dateutils import ( + today, + date_set_end_of_day, + form_input_from_date, + form_input_to_date, +) from dateutil.relativedelta import relativedelta from flask import request -class EventSearchParams(object): +class EventSearchParams(object): def __init__(self): self._date_from = None self._date_to = None @@ -77,30 +82,30 @@ class EventSearchParams(object): self.date_to = date_set_end_of_day(today + relativedelta(months=3)) def load_from_request(self): - if 'date_from' in request.args: - self.date_from_str = request.args['date_from'] + if "date_from" in request.args: + self.date_from_str = request.args["date_from"] - if 'date_to' in request.args: - self.date_to_str = request.args['date_to'] + if "date_to" in request.args: + self.date_to_str = request.args["date_to"] - if 'keyword' in request.args: - self.keyword = request.args['keyword'] + if "keyword" in request.args: + self.keyword = request.args["keyword"] if "coordinate" in request.args: - self.coordinate = request.args['coordinate'] + self.coordinate = request.args["coordinate"] if "distance" in request.args: - self.distance = request.args['distance'] + self.distance = request.args["distance"] if "category_id" in request.args: - category_ids = request.args.getlist('category_id') - if '0' in category_ids: - category_ids.remove('0') + category_ids = request.args.getlist("category_id") + if "0" in category_ids: + category_ids.remove("0") if len(category_ids) > 0: self.category_id = category_ids if "weekday" in request.args: - self.weekday = request.args.getlist('weekday') + self.weekday = request.args.getlist("weekday") if "organizer_id" in request.args: - self.organizer_id = request.args['organizer_id'] + self.organizer_id = request.args["organizer_id"] diff --git a/project/services/event_suggestion.py b/project/services/event_suggestion.py index dc86348..b1c3d06 100644 --- a/project/services/event_suggestion.py +++ b/project/services/event_suggestion.py @@ -1,9 +1,15 @@ from project.models import EventReviewStatus, EventSuggestion from sqlalchemy import and_ + def get_event_reviews_badge_query(admin_unit): - return EventSuggestion.query.filter(and_(EventSuggestion.admin_unit_id == admin_unit.id, EventSuggestion.review_status == EventReviewStatus.inbox)) + return EventSuggestion.query.filter( + and_( + EventSuggestion.admin_unit_id == admin_unit.id, + EventSuggestion.review_status == EventReviewStatus.inbox, + ) + ) + def get_event_reviews_query(admin_unit): return EventSuggestion.query.filter(EventSuggestion.admin_unit_id == admin_unit.id) - diff --git a/project/services/location.py b/project/services/location.py index 9cbe361..bdcd0c2 100644 --- a/project/services/location.py +++ b/project/services/location.py @@ -1,9 +1,13 @@ +from project import db from project.models import Location -def upsert_location(street, postalCode, city, latitude = 0, longitude = 0, state = None): - result = Location.query.filter_by(street = street, postalCode=postalCode, city=city, state=state).first() + +def upsert_location(street, postalCode, city, latitude=0, longitude=0, state=None): + result = Location.query.filter_by( + street=street, postalCode=postalCode, city=city, state=state + ).first() if result is None: - result = Location(street = street, postalCode=postalCode, city=city, state=state) + result = Location(street=street, postalCode=postalCode, city=city, state=state) db.session.add(result) result.latitude = latitude @@ -20,4 +24,4 @@ def assign_location_values(target, origin): target.state = origin.state target.country = origin.country target.latitude = origin.latitude - target.longitude = origin.longitude \ No newline at end of file + target.longitude = origin.longitude diff --git a/project/services/organizer.py b/project/services/organizer.py index cec32ff..19440e9 100644 --- a/project/services/organizer.py +++ b/project/services/organizer.py @@ -1,16 +1,25 @@ -from project.models import EventOrganizer, EventPlace -from sqlalchemy import and_, or_, not_ -from sqlalchemy.sql import asc, func +from project import db +from project.models import EventOrganizer, EventPlace, Location +from sqlalchemy import and_ +from sqlalchemy.sql import func + def upsert_event_organizer(admin_unit_id, name): - result = EventOrganizer.query.filter(and_(EventOrganizer.name == name, EventOrganizer.admin_unit_id == admin_unit_id)).first() + result = EventOrganizer.query.filter( + and_(EventOrganizer.name == name, EventOrganizer.admin_unit_id == admin_unit_id) + ).first() if result is None: - result = EventOrganizer(name = name, admin_unit_id=admin_unit_id) + result = EventOrganizer(name=name, admin_unit_id=admin_unit_id) result.location = Location() db.session.add(result) return result + def get_event_places(organizer_id): organizer = EventOrganizer.query.get(organizer_id) - return EventPlace.query.filter(EventPlace.admin_unit_id==organizer.admin_unit_id).order_by(func.lower(EventPlace.name)).all() \ No newline at end of file + return ( + EventPlace.query.filter(EventPlace.admin_unit_id == organizer.admin_unit_id) + .order_by(func.lower(EventPlace.name)) + .all() + ) diff --git a/project/services/place.py b/project/services/place.py index ca16437..ca96f71 100644 --- a/project/services/place.py +++ b/project/services/place.py @@ -1,14 +1,29 @@ -from project.models import EventPlace -from sqlalchemy.sql import asc, func +from project import db +from project.models import EventPlace, Location +from sqlalchemy.sql import and_, func + def upsert_event_place(admin_unit_id, organizer_id, name): - result = EventPlace.query.filter(and_(EventPlace.name == name, EventPlace.admin_unit_id == admin_unit_id, EventPlace.organizer_id == organizer_id)).first() + result = EventPlace.query.filter( + and_( + EventPlace.name == name, + EventPlace.admin_unit_id == admin_unit_id, + EventPlace.organizer_id == organizer_id, + ) + ).first() if result is None: - result = EventPlace(name = name, admin_unit_id=admin_unit_id, organizer_id=organizer_id) + result = EventPlace( + name=name, admin_unit_id=admin_unit_id, organizer_id=organizer_id + ) result.location = Location() db.session.add(result) return result + def get_event_places(admin_unit_id): - return EventPlace.query.filter(EventPlace.admin_unit_id==admin_unit_id).order_by(func.lower(EventPlace.name)).all() \ No newline at end of file + return ( + EventPlace.query.filter(EventPlace.admin_unit_id == admin_unit_id) + .order_by(func.lower(EventPlace.name)) + .all() + ) diff --git a/project/services/reference.py b/project/services/reference.py index 67f3b06..99e2c30 100644 --- a/project/services/reference.py +++ b/project/services/reference.py @@ -1,20 +1,44 @@ from project import db -from project.models import EventReference, EventReferenceRequest, EventReferenceRequestReviewStatus -from sqlalchemy import and_, or_, not_ +from project.models import ( + EventReference, + EventReferenceRequest, + EventReferenceRequestReviewStatus, +) +from sqlalchemy import and_ + def create_event_reference_for_request(request): - result = EventReference.query.filter(and_(EventReference.event_id == request.event_id, - EventReference.admin_unit_id == request.admin_unit_id)).first() + result = EventReference.query.filter( + and_( + EventReference.event_id == request.event_id, + EventReference.admin_unit_id == request.admin_unit_id, + ) + ).first() if result is None: - result = EventReference(event_id = request.event_id, - admin_unit_id = request.admin_unit_id) + result = EventReference( + event_id=request.event_id, admin_unit_id=request.admin_unit_id + ) db.session.add(result) return result + def get_reference_requests_incoming_query(admin_unit): - return EventReferenceRequest.query.filter(and_(EventReferenceRequest.review_status != EventReferenceRequestReviewStatus.verified, EventReferenceRequest.admin_unit_id == admin_unit.id)) + return EventReferenceRequest.query.filter( + and_( + EventReferenceRequest.review_status + != EventReferenceRequestReviewStatus.verified, + EventReferenceRequest.admin_unit_id == admin_unit.id, + ) + ) + def get_reference_requests_incoming_badge_query(admin_unit): - return EventReferenceRequest.query.filter(and_(EventReferenceRequest.review_status == EventReferenceRequestReviewStatus.inbox, EventReferenceRequest.admin_unit_id == admin_unit.id)) \ No newline at end of file + return EventReferenceRequest.query.filter( + and_( + EventReferenceRequest.review_status + == EventReferenceRequestReviewStatus.inbox, + EventReferenceRequest.admin_unit_id == admin_unit.id, + ) + ) diff --git a/project/services/user.py b/project/services/user.py index 3cf9bde..bb3a6d2 100644 --- a/project/services/user.py +++ b/project/services/user.py @@ -1,17 +1,22 @@ from project import user_datastore -from flask_security import Security, current_user, auth_required, roles_required, hash_password +from flask_security import hash_password + def upsert_user(email, password="password"): result = user_datastore.find_user(email=email) if result is None: - result = user_datastore.create_user(email=email, password=hash_password(password)) + result = user_datastore.create_user( + email=email, password=hash_password(password) + ) return result + def add_roles_to_user(user_name, role_names): user = upsert_user(user_name) for role_name in role_names: user_datastore.add_role_to_user(user, role_name) + def upsert_user_role(role_name, role_title, permissions): role = user_datastore.find_or_create_role(role_name) role.title = role_title @@ -19,5 +24,6 @@ def upsert_user_role(role_name, role_title, permissions): role.add_permissions(permissions) return role + def find_user_by_email(email): - return user_datastore.find_user(email=email) \ No newline at end of file + return user_datastore.find_user(email=email) diff --git a/project/static/jquery.recurrenceinput.js b/project/static/jquery.recurrenceinput.js index 82bbd3d..dce1249 100644 --- a/project/static/jquery.recurrenceinput.js +++ b/project/static/jquery.recurrenceinput.js @@ -164,7 +164,7 @@ rangeByEndDateHuman: 'ends on', including: ', and also', - except: ', except for', + except Exception: ', except for', cancel: 'Cancel', save: 'Save', diff --git a/project/static/site.js b/project/static/site.js index 86f7a98..ed0e70a 100644 --- a/project/static/site.js +++ b/project/static/site.js @@ -51,7 +51,7 @@ jQuery.tools.recurrenceinput.localize('de', { rangeByEndDate: 'Bis ', rangeByEndDateHuman: 'endet am ', including: ', und auch ', - except: ', ausser für', + except Exception: ', ausser für', cancel: 'Abbrechen', save: 'Speichern', recurrenceStart: 'Beginn der Wiederholung', diff --git a/project/utils.py b/project/utils.py index d18c509..3ae727b 100644 --- a/project/utils.py +++ b/project/utils.py @@ -1,7 +1,9 @@ from flask_babelex import lazy_gettext + def get_event_category_name(category): - return lazy_gettext('Event_' + category.name) + return lazy_gettext("Event_" + category.name) + def get_localized_enum_name(enum): - return lazy_gettext(enum.__class__.__name__ + '.' + enum.name) \ No newline at end of file + return lazy_gettext(enum.__class__.__name__ + "." + enum.name) diff --git a/project/views/admin.py b/project/views/admin.py index 083413d..128ef30 100644 --- a/project/views/admin.py +++ b/project/views/admin.py @@ -1,18 +1,16 @@ -from project import app, db +from project import app from project.models import AdminUnit -from flask import render_template, flash, url_for, redirect, request, jsonify -from flask_babelex import gettext -from flask_security import auth_required, roles_required -from project.access import has_access, access_or_401 -from sqlalchemy.sql import asc, func +from flask import render_template +from flask_security import roles_required + @app.route("/admin") @roles_required("admin") def admin(): - return render_template('admin/admin.html') + return render_template("admin/admin.html") + @app.route("/admin/admin_units") @roles_required("admin") def admin_admin_units(): - return render_template('admin/admin_units.html', - admin_units=AdminUnit.query.all()) + return render_template("admin/admin_units.html", admin_units=AdminUnit.query.all()) diff --git a/project/views/admin_unit.py b/project/views/admin_unit.py index a9b1468..759df7b 100644 --- a/project/views/admin_unit.py +++ b/project/views/admin_unit.py @@ -1,20 +1,26 @@ from project import app, db -from flask import url_for, render_template, request, redirect, flash +from flask import url_for, render_template, redirect, flash from flask_babelex import gettext from flask_security import auth_required, current_user -from project.models import AdminUnitMemberInvitation from sqlalchemy.exc import SQLAlchemyError -from project.access import get_admin_unit_for_manage_or_404, access_or_401, has_access +from project.access import get_admin_unit_for_manage_or_404, has_access from project.forms.admin_unit import CreateAdminUnitForm, UpdateAdminUnitForm -from project.views.utils import upsert_image_with_data, handleSqlError, permission_missing, flash_errors +from project.views.utils import ( + upsert_image_with_data, + handleSqlError, + permission_missing, + flash_errors, +) from project.models import AdminUnit, Location, EventOrganizer from project.services.admin_unit import add_user_to_admin_unit_with_roles from project.services.location import assign_location_values + def update_admin_unit_with_form(admin_unit, form): form.populate_obj(admin_unit) -@app.route("/admin_unit/create", methods=('GET', 'POST')) + +@app.route("/admin_unit/create", methods=("GET", "POST")) @auth_required() def admin_unit_create(): form = CreateAdminUnitForm() @@ -28,7 +34,9 @@ def admin_unit_create(): db.session.add(admin_unit) # Aktuellen Nutzer als Admin hinzufügen - add_user_to_admin_unit_with_roles(current_user, admin_unit, ['admin', 'event_verifier']) + add_user_to_admin_unit_with_roles( + current_user, admin_unit, ["admin", "event_verifier"] + ) db.session.commit() # Organizer anlegen @@ -42,27 +50,32 @@ def admin_unit_create(): organizer.location = Location() assign_location_values(organizer.location, admin_unit.location) if admin_unit.logo: - organizer.logo = upsert_image_with_data(organizer.logo, admin_unit.logo.data, admin_unit.logo.encoding_format) + organizer.logo = upsert_image_with_data( + organizer.logo, + admin_unit.logo.data, + admin_unit.logo.encoding_format, + ) db.session.add(organizer) db.session.commit() - flash(gettext('Admin unit successfully created'), 'success') - return redirect(url_for('manage_admin_unit', id=admin_unit.id)) + flash(gettext("Admin unit successfully created"), "success") + return redirect(url_for("manage_admin_unit", id=admin_unit.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('admin_unit/create.html', form=form) + return render_template("admin_unit/create.html", form=form) -@app.route('/admin_unit//update', methods=('GET', 'POST')) + +@app.route("/admin_unit//update", methods=("GET", "POST")) @auth_required() def admin_unit_update(id): admin_unit = get_admin_unit_for_manage_or_404(id) - if not has_access(admin_unit, 'admin_unit:update'): - return permission_missing(url_for('manage_admin_unit', id=admin_unit.id)) + if not has_access(admin_unit, "admin_unit:update"): + return permission_missing(url_for("manage_admin_unit", id=admin_unit.id)) form = UpdateAdminUnitForm(obj=admin_unit) @@ -71,14 +84,12 @@ def admin_unit_update(id): try: db.session.commit() - flash(gettext('AdminUnit successfully updated'), 'success') - return redirect(url_for('admin_unit_update', id=admin_unit.id)) + flash(gettext("AdminUnit successfully updated"), "success") + return redirect(url_for("admin_unit_update", id=admin_unit.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('admin_unit/update.html', - form=form, - admin_unit=admin_unit) \ No newline at end of file + return render_template("admin_unit/update.html", form=form, admin_unit=admin_unit) diff --git a/project/views/admin_unit_member.py b/project/views/admin_unit_member.py index 4719d1a..39e798d 100644 --- a/project/views/admin_unit_member.py +++ b/project/views/admin_unit_member.py @@ -1,25 +1,36 @@ from project import app, db -from flask import url_for, render_template, request, redirect, flash +from flask import url_for, render_template, redirect, flash from flask_babelex import gettext -from flask_security import auth_required, current_user +from flask_security import auth_required from project.models import AdminUnitMember, AdminUnitMemberRole -from project.forms.admin_unit_member import DeleteAdminUnitMemberForm, UpdateAdminUnitMemberForm -from project.views.utils import permission_missing, send_mail, handleSqlError, flash_errors -from project.access import get_admin_unit_for_manage_or_404, has_access +from project.forms.admin_unit_member import ( + DeleteAdminUnitMemberForm, + UpdateAdminUnitMemberForm, +) +from project.views.utils import ( + permission_missing, + handleSqlError, + flash_errors, +) +from project.access import has_access from project.services.admin_unit import add_roles_to_admin_unit_member from sqlalchemy.exc import SQLAlchemyError -@app.route('/manage/member//update', methods=('GET', 'POST')) + +@app.route("/manage/member//update", methods=("GET", "POST")) @auth_required() def manage_admin_unit_member_update(id): member = AdminUnitMember.query.get_or_404(id) admin_unit = member.adminunit - if not has_access(admin_unit, 'admin_unit.members:update'): - return permission_missing(url_for('manage_admin_unit', id=admin_unit.id)) + if not has_access(admin_unit, "admin_unit.members:update"): + return permission_missing(url_for("manage_admin_unit", id=admin_unit.id)) form = UpdateAdminUnitMemberForm() - form.roles.choices = [(c.name, gettext(c.title)) for c in AdminUnitMemberRole.query.order_by(AdminUnitMemberRole.id).all()] + form.roles.choices = [ + (c.name, gettext(c.title)) + for c in AdminUnitMemberRole.query.order_by(AdminUnitMemberRole.id).all() + ] if form.validate_on_submit(): member.roles.clear() @@ -27,45 +38,43 @@ def manage_admin_unit_member_update(id): try: db.session.commit() - flash(gettext('Member successfully updated'), 'success') - return redirect(url_for('manage_admin_unit_members', id=admin_unit.id)) + flash(gettext("Member successfully updated"), "success") + return redirect(url_for("manage_admin_unit_members", id=admin_unit.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: form.roles.data = [c.name for c in member.roles] - return render_template('admin_unit/update_member.html', - admin_unit=admin_unit, - member=member, - form=form) + return render_template( + "admin_unit/update_member.html", admin_unit=admin_unit, member=member, form=form + ) -@app.route('/manage/member//delete', methods=('GET', 'POST')) + +@app.route("/manage/member//delete", methods=("GET", "POST")) @auth_required() def manage_admin_unit_member_delete(id): member = AdminUnitMember.query.get_or_404(id) admin_unit = member.adminunit - if not has_access(admin_unit, 'admin_unit.members:delete'): - return permission_missing(url_for('manage_admin_unit', id=admin_unit.id)) + if not has_access(admin_unit, "admin_unit.members:delete"): + return permission_missing(url_for("manage_admin_unit", id=admin_unit.id)) form = DeleteAdminUnitMemberForm() if form.validate_on_submit(): if form.email.data != member.user.email: - flash(gettext('Entered email does not match member email'), 'danger') + flash(gettext("Entered email does not match member email"), "danger") else: try: db.session.delete(member) db.session.commit() - flash(gettext('Member successfully deleted'), 'success') - return redirect(url_for('manage_admin_unit_members', id=admin_unit.id)) + flash(gettext("Member successfully deleted"), "success") + return redirect(url_for("manage_admin_unit_members", id=admin_unit.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('manage/delete_member.html', - form=form, - member=member) \ No newline at end of file + return render_template("manage/delete_member.html", form=form, member=member) diff --git a/project/views/admin_unit_member_invitation.py b/project/views/admin_unit_member_invitation.py index 8cca92c..063c818 100644 --- a/project/views/admin_unit_member_invitation.py +++ b/project/views/admin_unit_member_invitation.py @@ -1,113 +1,130 @@ from project import app, db -from flask import url_for, render_template, request, redirect, flash +from flask import url_for, render_template, redirect, flash from flask_babelex import gettext from flask_security import auth_required, current_user from project.models import AdminUnitMemberInvitation, AdminUnitMemberRole -from project.forms.admin_unit_member import NegotiateAdminUnitMemberInvitationForm, InviteAdminUnitMemberForm, DeleteAdminUnitInvitationForm -from project.views.utils import permission_missing, send_mail, handleSqlError, flash_errors +from project.forms.admin_unit_member import ( + NegotiateAdminUnitMemberInvitationForm, + InviteAdminUnitMemberForm, + DeleteAdminUnitInvitationForm, +) +from project.views.utils import ( + permission_missing, + send_mail, + handleSqlError, + flash_errors, +) from project.access import get_admin_unit_for_manage_or_404, has_access from project.services.admin_unit import add_user_to_admin_unit_with_roles from project.services.user import find_user_by_email from sqlalchemy.exc import SQLAlchemyError -@app.route('/invitations/', methods=('GET', 'POST')) + +@app.route("/invitations/", methods=("GET", "POST")) def admin_unit_member_invitation(id): invitation = AdminUnitMemberInvitation.query.get_or_404(id) # Wenn Email nicht als Nutzer vorhanden, dann direkt zu Registrierung if not find_user_by_email(invitation.email): - return redirect(url_for('security.register')) + return redirect(url_for("security.register")) if not current_user.is_authenticated: return app.login_manager.unauthorized() if invitation.email != current_user.email: - return permission_missing(url_for('profile')) + return permission_missing(url_for("profile")) form = NegotiateAdminUnitMemberInvitationForm() if form.validate_on_submit(): try: if form.accept.data: - message = gettext('Invitation successfully accepted') - roles = invitation.roles.split(',') - add_user_to_admin_unit_with_roles(current_user, invitation.adminunit, roles) + message = gettext("Invitation successfully accepted") + roles = invitation.roles.split(",") + add_user_to_admin_unit_with_roles( + current_user, invitation.adminunit, roles + ) else: - message = gettext('Invitation successfully declined') + message = gettext("Invitation successfully declined") db.session.delete(invitation) db.session.commit() - flash(message, 'success') - return redirect(url_for('manage')) + flash(message, "success") + return redirect(url_for("manage")) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") - return render_template('invitation/read.html', - form=form, - invitation=invitation) + return render_template("invitation/read.html", form=form, invitation=invitation) -@app.route('/manage/admin_unit//members/invite', methods=('GET', 'POST')) + +@app.route("/manage/admin_unit//members/invite", methods=("GET", "POST")) @auth_required() def manage_admin_unit_member_invite(id): admin_unit = get_admin_unit_for_manage_or_404(id) - if not has_access(admin_unit, 'admin_unit.members:invite'): - return permission_missing(url_for('manage_admin_unit', id=admin_unit.id)) + if not has_access(admin_unit, "admin_unit.members:invite"): + return permission_missing(url_for("manage_admin_unit", id=admin_unit.id)) form = InviteAdminUnitMemberForm() - form.roles.choices = [(c.name, gettext(c.title)) for c in AdminUnitMemberRole.query.order_by(AdminUnitMemberRole.id).all()] + form.roles.choices = [ + (c.name, gettext(c.title)) + for c in AdminUnitMemberRole.query.order_by(AdminUnitMemberRole.id).all() + ] if form.validate_on_submit(): invitation = AdminUnitMemberInvitation() invitation.admin_unit_id = admin_unit.id form.populate_obj(invitation) - invitation.roles = ','.join(form.roles.data) + invitation.roles = ",".join(form.roles.data) try: db.session.add(invitation) db.session.commit() - send_mail(invitation.email, - gettext('You have received an invitation'), - 'invitation_notice', - invitation=invitation) + send_mail( + invitation.email, + gettext("You have received an invitation"), + "invitation_notice", + invitation=invitation, + ) - flash(gettext('Invitation successfully sent'), 'success') - return redirect(url_for('manage_admin_unit_members', id=admin_unit.id)) + flash(gettext("Invitation successfully sent"), "success") + return redirect(url_for("manage_admin_unit_members", id=admin_unit.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') - return render_template('admin_unit/invite_member.html', - admin_unit=admin_unit, - form=form) + flash(handleSqlError(e), "danger") + return render_template( + "admin_unit/invite_member.html", admin_unit=admin_unit, form=form + ) -@app.route('/manage/invitation//delete', methods=('GET', 'POST')) + +@app.route("/manage/invitation//delete", methods=("GET", "POST")) @auth_required() def manage_admin_unit_invitation_delete(id): invitation = AdminUnitMemberInvitation.query.get_or_404(id) admin_unit = invitation.adminunit - if not has_access(admin_unit, 'admin_unit.members:invite'): - return permission_missing(url_for('manage_admin_unit', id=id)) + if not has_access(admin_unit, "admin_unit.members:invite"): + return permission_missing(url_for("manage_admin_unit", id=id)) form = DeleteAdminUnitInvitationForm() if form.validate_on_submit(): if form.email.data != invitation.email: - flash(gettext('Entered email does not match invitation email'), 'danger') + flash(gettext("Entered email does not match invitation email"), "danger") else: try: db.session.delete(invitation) db.session.commit() - flash(gettext('Invitation successfully deleted'), 'success') - return redirect(url_for('manage_admin_unit_members', id=admin_unit.id)) + flash(gettext("Invitation successfully deleted"), "success") + return redirect(url_for("manage_admin_unit_members", id=admin_unit.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('manage/delete_invitation.html', - form=form, - invitation=invitation) \ No newline at end of file + return render_template( + "manage/delete_invitation.html", form=form, invitation=invitation + ) diff --git a/project/views/api.py b/project/views/api.py index 3164eca..6210a94 100644 --- a/project/views/api.py +++ b/project/views/api.py @@ -7,11 +7,18 @@ from project.services.event import get_event_dates_query from project.services.event_search import EventSearchParams from project.services.organizer import get_event_places + @app.route("/api/events") def api_events(): - dates = EventDate.query.join(Event).filter(EventDate.start >= today).order_by(EventDate.start).all() + dates = ( + EventDate.query.join(Event) + .filter(EventDate.start >= today) + .order_by(EventDate.start) + .all() + ) return json_from_event_dates(dates) + @app.route("/api/event_dates") def api_event_dates(): params = EventSearchParams() @@ -20,9 +27,12 @@ def api_event_dates(): dates = get_event_dates_query(params).paginate() return json_from_event_dates(dates.items) + @app.route("/api//event_dates") def api_infoscreen(au_short_name): - admin_unit = AdminUnit.query.filter(AdminUnit.short_name == au_short_name).first_or_404() + admin_unit = AdminUnit.query.filter( + AdminUnit.short_name == au_short_name + ).first_or_404() params = EventSearchParams() params.load_from_request() @@ -31,6 +41,7 @@ def api_infoscreen(au_short_name): dates = get_event_dates_query(params).paginate() return json_from_event_dates(dates.items) + @app.route("/api/organizer//event_places") def api_event_places(id): places = get_event_places(id) @@ -44,16 +55,17 @@ def api_event_places(id): return jsonify(result) + def json_from_event_dates(dates): structured_events = list() for event_date in dates: structured_event = get_sd_for_event_date(event_date) - structured_event.pop('@context', None) + structured_event.pop("@context", None) structured_events.append(structured_event) result = {} result["@context"] = "https://schema.org" result["@type"] = "Project" result["name"] = "Prototyp" - result['event'] = structured_events - return jsonify(result) \ No newline at end of file + result["event"] = structured_events + return jsonify(result) diff --git a/project/views/event.py b/project/views/event.py index 54f3314..b7fd596 100644 --- a/project/views/event.py +++ b/project/views/event.py @@ -1,58 +1,95 @@ from project import app, db -from project.models import User, Event, EventDate, EventReviewStatus, AdminUnit, AdminUnitMember, EventOrganizer, EventCategory, EventSuggestion -from flask import render_template, flash, url_for, redirect, request, jsonify, abort +from project.models import ( + Event, + EventDate, + EventReviewStatus, + AdminUnit, + EventOrganizer, + EventCategory, + EventSuggestion, +) +from flask import render_template, flash, url_for, redirect, request, jsonify from flask_babelex import gettext -from flask_security import auth_required -from project.access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission +from project.access import ( + has_access, + access_or_401, + can_reference_event, +) from project.dateutils import today from datetime import datetime from project.forms.event import CreateEventForm, UpdateEventForm, DeleteEventForm -from project.views.utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError, flash_message +from project.views.utils import ( + flash_errors, + handleSqlError, + flash_message, +) from project.utils import get_event_category_name -from project.services.event import upsert_event_category, update_event_dates_with_recurrence_rule +from project.services.event import ( + upsert_event_category, + update_event_dates_with_recurrence_rule, +) from project.services.place import get_event_places -from sqlalchemy.sql import asc, func +from sqlalchemy.sql import func from sqlalchemy.exc import SQLAlchemyError from project.views.event_suggestion import send_event_suggestion_review_status_mail -@app.route('/event/') + +@app.route("/event/") def event(event_id): event = Event.query.get_or_404(event_id) user_rights = get_user_rights(event) - dates = EventDate.query.with_parent(event).filter(EventDate.start >= today).order_by(EventDate.start).all() + dates = ( + EventDate.query.with_parent(event) + .filter(EventDate.start >= today) + .order_by(EventDate.start) + .all() + ) - return render_template('event/read.html', - event=event, - dates=dates, - user_rights=user_rights) + return render_template( + "event/read.html", event=event, dates=dates, user_rights=user_rights + ) -@app.route("/admin_unit//events/create", methods=('GET', 'POST')) + +@app.route("/admin_unit//events/create", methods=("GET", "POST")) def event_create_for_admin_unit_id(id): admin_unit = AdminUnit.query.get_or_404(id) - access_or_401(admin_unit, 'event:create') + access_or_401(admin_unit, "event:create") - form = CreateEventForm(admin_unit_id=admin_unit.id, category_ids=[upsert_event_category('Other').id]) + form = CreateEventForm( + admin_unit_id=admin_unit.id, category_ids=[upsert_event_category("Other").id] + ) prepare_event_form(form, admin_unit) # Vorlagen event_suggestion = None event_template = None - event_template_id = int(request.args.get('template_id')) if 'template_id' in request.args else 0 + event_template_id = ( + int(request.args.get("template_id")) if "template_id" in request.args else 0 + ) if event_template_id > 0: event_template = Event.query.get_or_404(event_template_id) if not form.is_submitted(): form.process(obj=event_template) if not event_template: - event_suggestion_id = int(request.args.get('event_suggestion_id')) if 'event_suggestion_id' in request.args else 0 + event_suggestion_id = ( + int(request.args.get("event_suggestion_id")) + if "event_suggestion_id" in request.args + else 0 + ) if event_suggestion_id > 0: event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id) - access_or_401(event_suggestion.admin_unit, 'event:verify') + access_or_401(event_suggestion.admin_unit, "event:verify") if event_suggestion.verified and event_suggestion.event_id: - return redirect(url_for('event_suggestion_review_status', event_suggestion_id=event_suggestion.id)) + return redirect( + url_for( + "event_suggestion_review_status", + event_suggestion_id=event_suggestion.id, + ) + ) prepare_event_form_for_suggestion(form, event_suggestion) if form.is_submitted(): @@ -81,21 +118,27 @@ def event_create_for_admin_unit_id(id): if event_suggestion: send_event_suggestion_review_status_mail(event_suggestion) - flash_message(gettext('Event successfully created'), url_for('event', event_id=event.id)) - return redirect(url_for('manage_admin_unit_events', id=event.admin_unit_id)) + flash_message( + gettext("Event successfully created"), + url_for("event", event_id=event.id), + ) + return redirect(url_for("manage_admin_unit_events", id=event.admin_unit_id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('event/create.html', form=form, event_suggestion=event_suggestion) + return render_template( + "event/create.html", form=form, event_suggestion=event_suggestion + ) -@app.route('/event//update', methods=('GET', 'POST')) + +@app.route("/event//update", methods=("GET", "POST")) def event_update(event_id): event = Event.query.get_or_404(event_id) - access_or_401(event.admin_unit, 'event:update') + access_or_401(event.admin_unit, "event:update") - form = UpdateEventForm(obj=event,start=event.start,end=event.end) + form = UpdateEventForm(obj=event, start=event.start, end=event.end) prepare_event_form(form, event.admin_unit) if not form.is_submitted(): @@ -106,72 +149,86 @@ def event_update(event_id): try: db.session.commit() - flash_message(gettext('Event successfully updated'), url_for('event', event_id=event.id)) - return redirect(url_for('manage_admin_unit_events', id=event.admin_unit_id)) + flash_message( + gettext("Event successfully updated"), + url_for("event", event_id=event.id), + ) + return redirect(url_for("manage_admin_unit_events", id=event.admin_unit_id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('event/update.html', - form=form, - event=event) + return render_template("event/update.html", form=form, event=event) -@app.route('/event//delete', methods=('GET', 'POST')) + +@app.route("/event//delete", methods=("GET", "POST")) def event_delete(event_id): event = Event.query.get_or_404(event_id) - access_or_401(event.admin_unit, 'event:delete') + access_or_401(event.admin_unit, "event:delete") form = DeleteEventForm() if form.validate_on_submit(): if form.name.data != event.name: - flash(gettext('Entered name does not match event name'), 'danger') + flash(gettext("Entered name does not match event name"), "danger") else: try: admin_unit_id = event.admin_unit.id db.session.delete(event) db.session.commit() - flash(gettext('Event successfully deleted'), 'success') - return redirect(url_for('manage_admin_unit_events', id=admin_unit_id)) + flash(gettext("Event successfully deleted"), "success") + return redirect(url_for("manage_admin_unit_events", id=admin_unit_id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('event/delete.html', - form=form, - event=event) + return render_template("event/delete.html", form=form, event=event) -@app.route("/events/rrule", methods=['POST']) + +@app.route("/events/rrule", methods=["POST"]) def event_rrule(): - year = request.json['year'] - month = request.json['month'] - day = request.json['day'] - rrule_str = request.json['rrule'] - output_format = request.json['format'] - start = int(request.json['start']) + year = request.json["year"] + month = request.json["month"] + day = request.json["day"] + rrule_str = request.json["rrule"] + start = int(request.json["start"]) batch_size = 10 start_date = datetime(year, month, day) from project.dateutils import calculate_occurrences - result = calculate_occurrences(start_date, '"%d.%m.%Y"', rrule_str, start, batch_size) + + result = calculate_occurrences( + start_date, '"%d.%m.%Y"', rrule_str, start, batch_size + ) return jsonify(result) + def get_event_category_choices(): - return sorted([(c.id, get_event_category_name(c)) for c in EventCategory.query.all()], key=lambda category: category[1]) + return sorted( + [(c.id, get_event_category_name(c)) for c in EventCategory.query.all()], + key=lambda category: category[1], + ) + def prepare_event_form(form, admin_unit): - form.organizer_id.choices = [(o.id, o.name) for o in EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name))] + form.organizer_id.choices = [ + (o.id, o.name) + for o in EventOrganizer.query.filter( + EventOrganizer.admin_unit_id == admin_unit.id + ).order_by(func.lower(EventOrganizer.name)) + ] form.category_ids.choices = get_event_category_choices() places = get_event_places(admin_unit.id) form.event_place_id.choices = [(p.id, p.name) for p in places] - form.organizer_id.choices.insert(0, (0, '')) - form.event_place_id.choices.insert(0, (0, '')) + form.organizer_id.choices.insert(0, (0, "")) + form.event_place_id.choices.insert(0, (0, "")) + def prepare_event_form_for_suggestion(form, event_suggestion): form.name.data = event_suggestion.name @@ -194,16 +251,22 @@ def prepare_event_form_for_suggestion(form, event_suggestion): form.organizer_choice.data = 2 form.new_organizer.form.name.data = event_suggestion.organizer_text -def update_event_with_form(event, form, event_suggestion = None): + +def update_event_with_form(event, form, event_suggestion=None): form.populate_obj(event) - event.categories = EventCategory.query.filter(EventCategory.id.in_(form.category_ids.data)).all() + event.categories = EventCategory.query.filter( + EventCategory.id.in_(form.category_ids.data) + ).all() update_event_dates_with_recurrence_rule(event, form.start.data, form.end.data) + def get_user_rights(event): return { - "can_duplicate_event": has_access(event.admin_unit, 'event:create'), - "can_verify_event": has_access(event.admin_unit, 'event:verify'), - "can_update_event": has_access(event.admin_unit, 'event:update'), + "can_duplicate_event": has_access(event.admin_unit, "event:create"), + "can_verify_event": has_access(event.admin_unit, "event:verify"), + "can_update_event": has_access(event.admin_unit, "event:update"), "can_reference_event": can_reference_event(event), - "can_create_reference_request": has_access(event.admin_unit, 'reference_request:create') - } \ No newline at end of file + "can_create_reference_request": has_access( + event.admin_unit, "reference_request:create" + ), + } diff --git a/project/views/event_date.py b/project/views/event_date.py index 99db43e..0329be4 100644 --- a/project/views/event_date.py +++ b/project/views/event_date.py @@ -1,21 +1,18 @@ -from project import app, db -from project.models import Event, EventDate, EventReviewStatus -from flask import render_template, flash, url_for, redirect, request -from flask_babelex import gettext -from project.dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date -from dateutil.relativedelta import relativedelta -from project.views.utils import flash_errors, track_analytics, get_pagination_urls -from sqlalchemy import and_, or_, not_ +from project import app +from project.models import EventDate +from flask import render_template, url_for, redirect, request +from project.views.utils import flash_errors, track_analytics import json from project.jsonld import get_sd_for_event_date, DateTimeEncoder from project.services.event_search import EventSearchParams -from project.services.event import get_event_dates_query from project.forms.event_date import FindEventDateForm from project.views.event import get_event_category_choices, get_user_rights + def prepare_event_date_form(form): form.category_id.choices = get_event_category_choices() - form.category_id.choices.insert(0, (0, '')) + form.category_id.choices.insert(0, (0, "")) + @app.route("/eventdates") def event_dates(): @@ -30,20 +27,23 @@ def event_dates(): else: flash_errors(form) - return render_template('event_date/list.html', - form=form, - params=params) + return render_template("event_date/list.html", form=form, params=params) -@app.route('/eventdate/') + +@app.route("/eventdate/") def event_date(id): event_date = EventDate.query.get_or_404(id) - if 'src' in request.args: - track_analytics("event_date", str(id), request.args['src']) - return redirect(url_for('event_date', id=id)) + if "src" in request.args: + track_analytics("event_date", str(id), request.args["src"]) + return redirect(url_for("event_date", id=id)) - structured_data = json.dumps(get_sd_for_event_date(event_date), indent=2, cls=DateTimeEncoder) - return render_template('event_date/read.html', + structured_data = json.dumps( + get_sd_for_event_date(event_date), indent=2, cls=DateTimeEncoder + ) + return render_template( + "event_date/read.html", event_date=event_date, structured_data=structured_data, - user_rights = get_user_rights(event_date.event)) \ No newline at end of file + user_rights=get_user_rights(event_date.event), + ) diff --git a/project/views/event_place.py b/project/views/event_place.py index de84e20..d2a27c3 100644 --- a/project/views/event_place.py +++ b/project/views/event_place.py @@ -1,19 +1,26 @@ from project import app, db -from project.models import EventOrganizer, EventPlace, Location -from flask import render_template, flash, url_for, redirect, request, jsonify +from project.models import EventPlace, Location +from flask import render_template, flash, url_for, redirect from flask_babelex import gettext from flask_security import auth_required -from project.access import has_access, access_or_401, get_admin_unit_for_manage_or_404 -from project.forms.event_place import UpdateEventPlaceForm, CreateEventPlaceForm, DeleteEventPlaceForm -from project.views.utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError -from sqlalchemy.sql import asc, func +from project.access import access_or_401, get_admin_unit_for_manage_or_404 +from project.forms.event_place import ( + UpdateEventPlaceForm, + CreateEventPlaceForm, + DeleteEventPlaceForm, +) +from project.views.utils import ( + flash_errors, + handleSqlError, +) from sqlalchemy.exc import SQLAlchemyError -@app.route('/manage/admin_unit//places/create', methods=('GET', 'POST')) + +@app.route("/manage/admin_unit//places/create", methods=("GET", "POST")) @auth_required() def manage_admin_unit_places_create(id): admin_unit = get_admin_unit_for_manage_or_404(id) - access_or_401(admin_unit, 'place:create') + access_or_401(admin_unit, "place:create") form = CreateEventPlaceForm() @@ -26,18 +33,19 @@ def manage_admin_unit_places_create(id): try: db.session.add(place) db.session.commit() - flash(gettext('Place successfully created'), 'success') - return redirect(url_for('manage_admin_unit_event_places', id=admin_unit.id)) + flash(gettext("Place successfully created"), "success") + return redirect(url_for("manage_admin_unit_event_places", id=admin_unit.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') - return render_template('event_place/create.html', form=form) + flash(handleSqlError(e), "danger") + return render_template("event_place/create.html", form=form) -@app.route('/event_place//update', methods=('GET', 'POST')) + +@app.route("/event_place//update", methods=("GET", "POST")) @auth_required() def event_place_update(id): place = EventPlace.query.get_or_404(id) - access_or_401(place.adminunit, 'place:update') + access_or_401(place.adminunit, "place:update") form = UpdateEventPlaceForm(obj=place) @@ -46,44 +54,45 @@ def event_place_update(id): try: db.session.commit() - flash(gettext('Place successfully updated'), 'success') - return redirect(url_for('manage_admin_unit_event_places', id=place.admin_unit_id)) + flash(gettext("Place successfully updated"), "success") + return redirect( + url_for("manage_admin_unit_event_places", id=place.admin_unit_id) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") - return render_template('event_place/update.html', - form=form, - place=place) + return render_template("event_place/update.html", form=form, place=place) -@app.route('/event_place//delete', methods=('GET', 'POST')) + +@app.route("/event_place//delete", methods=("GET", "POST")) @auth_required() def event_place_delete(id): place = EventPlace.query.get_or_404(id) - access_or_401(place.adminunit, 'place:delete') + access_or_401(place.adminunit, "place:delete") form = DeleteEventPlaceForm() if form.validate_on_submit(): if form.name.data != place.name: - flash(gettext('Entered name does not match place name'), 'danger') + flash(gettext("Entered name does not match place name"), "danger") else: try: - admin_unit_id=place.admin_unit_id + admin_unit_id = place.admin_unit_id db.session.delete(place) db.session.commit() - flash(gettext('Place successfully deleted'), 'success') - return redirect(url_for('manage_admin_unit_event_places', id=admin_unit_id)) + flash(gettext("Place successfully deleted"), "success") + return redirect( + url_for("manage_admin_unit_event_places", id=admin_unit_id) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('event_place/delete.html', - form=form, - place=place) + return render_template("event_place/delete.html", form=form, place=place) + def update_event_place_with_form(place, form): form.populate_obj(place) - diff --git a/project/views/event_suggestion.py b/project/views/event_suggestion.py index 89e5051..c2b7bf2 100644 --- a/project/views/event_suggestion.py +++ b/project/views/event_suggestion.py @@ -1,34 +1,39 @@ from project import app, db -from project.models import EventSuggestion, User, Event, EventDate, EventReviewStatus, AdminUnit, AdminUnitMember, EventOrganizer, EventCategory -from flask import render_template, flash, url_for, redirect, request, jsonify, abort +from project.models import ( + EventSuggestion, + EventReviewStatus, +) +from flask import render_template, flash, url_for, redirect from flask_babelex import gettext -from flask_security import current_user -from project.access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission -from project.dateutils import today -from datetime import datetime +from project.access import access_or_401 from project.forms.event_suggestion import RejectEventSuggestionForm -from project.views.utils import flash_errors, send_mail, handleSqlError, flash_message -from project.utils import get_event_category_name -from project.services.event import upsert_event_category, update_event_dates_with_recurrence_rule -from sqlalchemy.sql import asc, func +from project.views.utils import flash_errors, send_mail, handleSqlError from sqlalchemy.exc import SQLAlchemyError -@app.route('/event_suggestion//review') + +@app.route("/event_suggestion//review") def event_suggestion_review(event_suggestion_id): event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id) - access_or_401(event_suggestion.admin_unit, 'event:verify') + access_or_401(event_suggestion.admin_unit, "event:verify") - return render_template('event_suggestion/review.html', + return render_template( + "event_suggestion/review.html", admin_unit=event_suggestion.admin_unit, - event_suggestion=event_suggestion) + event_suggestion=event_suggestion, + ) -@app.route('/event_suggestion//reject', methods=('GET', 'POST')) + +@app.route( + "/event_suggestion//reject", methods=("GET", "POST") +) def event_suggestion_reject(event_suggestion_id): event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id) - access_or_401(event_suggestion.admin_unit, 'event:verify') + access_or_401(event_suggestion.admin_unit, "event:verify") if event_suggestion.verified: - return redirect(url_for('event_suggestion_review', event_suggestion_id=event_suggestion.id)) + return redirect( + url_for("event_suggestion_review", event_suggestion_id=event_suggestion.id) + ) form = RejectEventSuggestionForm(obj=event_suggestion) @@ -42,29 +47,40 @@ def event_suggestion_reject(event_suggestion_id): try: db.session.commit() send_event_suggestion_review_status_mail(event_suggestion) - flash(gettext('Event suggestion successfully rejected'), 'success') - return redirect(url_for('manage_admin_unit_event_reviews', id=event_suggestion.admin_unit_id)) + flash(gettext("Event suggestion successfully rejected"), "success") + return redirect( + url_for( + "manage_admin_unit_event_reviews", id=event_suggestion.admin_unit_id + ) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('event_suggestion/reject.html', + return render_template( + "event_suggestion/reject.html", form=form, admin_unit=event_suggestion.admin_unit, - event_suggestion=event_suggestion) + event_suggestion=event_suggestion, + ) -@app.route('/event_suggestion//review_status') + +@app.route("/event_suggestion//review_status") def event_suggestion_review_status(event_suggestion_id): event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id) - return render_template('event_suggestion/review_status.html', - event_suggestion=event_suggestion) + return render_template( + "event_suggestion/review_status.html", event_suggestion=event_suggestion + ) + def send_event_suggestion_review_status_mail(event_suggestion): if event_suggestion.contact_email and event_suggestion.contact_email_notice: - send_mail(event_suggestion.contact_email, - gettext('Event review status updated'), - 'review_status_notice', - event_suggestion=event_suggestion) + send_mail( + event_suggestion.contact_email, + gettext("Event review status updated"), + "review_status_notice", + event_suggestion=event_suggestion, + ) diff --git a/project/views/image.py b/project/views/image.py index 0f1c060..d5c62e9 100644 --- a/project/views/image.py +++ b/project/views/image.py @@ -1,7 +1,8 @@ from project import app from project.models import Image -@app.route('/image/') + +@app.route("/image/") def image(id): image = Image.query.get_or_404(id) - return app.response_class(image.data, mimetype=image.encoding_format) \ No newline at end of file + return app.response_class(image.data, mimetype=image.encoding_format) diff --git a/project/views/manage.py b/project/views/manage.py index 6c6481a..27aa96c 100644 --- a/project/views/manage.py +++ b/project/views/manage.py @@ -1,12 +1,36 @@ from project import app, db -from project.models import AdminUnit, AdminUnitMember, AdminUnitMemberInvitation, Event, EventPlace, EventReviewStatus, EventOrganizer, User, EventSuggestion -from flask import render_template, flash, url_for, redirect, request, jsonify, make_response +from project.models import ( + AdminUnitMember, + AdminUnitMemberInvitation, + EventPlace, + EventOrganizer, + User, + EventSuggestion, +) +from flask import ( + render_template, + flash, + url_for, + redirect, + request, + make_response, +) from flask_babelex import gettext -from flask_security import auth_required, roles_required, current_user -from project.access import has_access, access_or_401, get_admin_unit_for_manage, get_admin_units_for_manage, get_admin_unit_for_manage_or_404 -from sqlalchemy.sql import asc, desc, func -from sqlalchemy import and_, or_, not_ -from project.views.utils import get_pagination_urls, permission_missing, handleSqlError, flash_errors +from flask_security import auth_required, current_user +from project.access import ( + has_access, + get_admin_unit_for_manage, + get_admin_units_for_manage, + get_admin_unit_for_manage_or_404, +) +from sqlalchemy.sql import desc, func +from sqlalchemy.exc import SQLAlchemyError +from project.views.utils import ( + get_pagination_urls, + permission_missing, + handleSqlError, + flash_errors, +) from project.forms.event_place import FindEventPlaceForm from project.forms.event import FindEventForm from project.forms.admin_unit import UpdateAdminUnitWidgetForm @@ -15,57 +39,72 @@ from project.services.event import get_events_query from project.services.event_suggestion import get_event_reviews_query from project.views.event import get_event_category_choices + @app.route("/manage") @auth_required() def manage(): try: - if 'manage_admin_unit_id' in request.cookies: - manage_admin_unit_id = int(request.cookies.get('manage_admin_unit_id')) + if "manage_admin_unit_id" in request.cookies: + manage_admin_unit_id = int(request.cookies.get("manage_admin_unit_id")) admin_unit = get_admin_unit_for_manage(manage_admin_unit_id) if admin_unit: - return redirect(url_for('manage_admin_unit', id=admin_unit.id)) - except: + return redirect(url_for("manage_admin_unit", id=admin_unit.id)) + except Exception: pass - return redirect(url_for('manage_admin_units')) + return redirect(url_for("manage_admin_units")) + @app.route("/manage/admin_units") @auth_required() def manage_admin_units(): admin_units = get_admin_units_for_manage() - invitations = AdminUnitMemberInvitation.query.filter(AdminUnitMemberInvitation.email == current_user.email).all() + invitations = AdminUnitMemberInvitation.query.filter( + AdminUnitMemberInvitation.email == current_user.email + ).all() admin_units.sort(key=lambda x: x.name) invitations.sort(key=lambda x: x.adminunit.name) - return render_template('manage/admin_units.html', - invitations=invitations, - admin_units=admin_units) + return render_template( + "manage/admin_units.html", invitations=invitations, admin_units=admin_units + ) -@app.route('/manage/admin_unit/') + +@app.route("/manage/admin_unit/") @auth_required() def manage_admin_unit(id): admin_unit = get_admin_unit_for_manage_or_404(id) - response = make_response(redirect(url_for('manage_admin_unit_events', id=admin_unit.id))) - response.set_cookie('manage_admin_unit_id', str(admin_unit.id)) + response = make_response( + redirect(url_for("manage_admin_unit_events", id=admin_unit.id)) + ) + response.set_cookie("manage_admin_unit_id", str(admin_unit.id)) return response -@app.route('/manage/admin_unit//reviews') + +@app.route("/manage/admin_unit//reviews") @auth_required() def manage_admin_unit_event_reviews(id): admin_unit = get_admin_unit_for_manage_or_404(id) - event_suggestions_paginate = get_event_reviews_query(admin_unit).order_by(desc(EventSuggestion.created_at)).paginate() + event_suggestions_paginate = ( + get_event_reviews_query(admin_unit) + .order_by(desc(EventSuggestion.created_at)) + .paginate() + ) event_suggestions = event_suggestions_paginate.items - return render_template('manage/reviews.html', + return render_template( + "manage/reviews.html", admin_unit=admin_unit, event_suggestions=event_suggestions, - pagination = get_pagination_urls(event_suggestions_paginate, id=id)) + pagination=get_pagination_urls(event_suggestions_paginate, id=id), + ) -@app.route('/manage/admin_unit//events') + +@app.route("/manage/admin_unit//events") @auth_required() def manage_admin_unit_events(id): admin_unit = get_admin_unit_for_manage_or_404(id) @@ -75,72 +114,107 @@ def manage_admin_unit_events(id): form = FindEventForm(formdata=request.args, obj=params) form.category_id.choices = get_event_category_choices() - form.category_id.choices.insert(0, (0, '')) + form.category_id.choices.insert(0, (0, "")) - organizers = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).all() + organizers = ( + EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id) + .order_by(func.lower(EventOrganizer.name)) + .all() + ) form.organizer_id.choices = [(o.id, o.name) for o in organizers] - form.organizer_id.choices.insert(0, (0, '')) + form.organizer_id.choices.insert(0, (0, "")) if form.validate(): form.populate_obj(params) params.admin_unit_id = admin_unit.id events = get_events_query(params).paginate() - return render_template('manage/events.html', + return render_template( + "manage/events.html", admin_unit=admin_unit, form=form, events=events.items, - pagination=get_pagination_urls(events, id=id)) + pagination=get_pagination_urls(events, id=id), + ) -@app.route('/manage/admin_unit//organizers') + +@app.route("/manage/admin_unit//organizers") @auth_required() def manage_admin_unit_organizers(id): admin_unit = get_admin_unit_for_manage_or_404(id) - organizers = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).paginate() + organizers = ( + EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id) + .order_by(func.lower(EventOrganizer.name)) + .paginate() + ) - return render_template('manage/organizers.html', + return render_template( + "manage/organizers.html", admin_unit=admin_unit, organizers=organizers.items, - pagination=get_pagination_urls(organizers, id=id)) + pagination=get_pagination_urls(organizers, id=id), + ) -@app.route('/manage/admin_unit//event_places') + +@app.route("/manage/admin_unit//event_places") @auth_required() def manage_admin_unit_event_places(id): admin_unit = get_admin_unit_for_manage_or_404(id) form = FindEventPlaceForm(**request.args) - places = EventPlace.query.filter(EventPlace.admin_unit_id == admin_unit.id).order_by(func.lower(EventPlace.name)).paginate() - return render_template('manage/places.html', + places = ( + EventPlace.query.filter(EventPlace.admin_unit_id == admin_unit.id) + .order_by(func.lower(EventPlace.name)) + .paginate() + ) + return render_template( + "manage/places.html", admin_unit=admin_unit, form=form, places=places.items, - pagination=get_pagination_urls(places, id=id)) + pagination=get_pagination_urls(places, id=id), + ) -@app.route('/manage/admin_unit//members') + +@app.route("/manage/admin_unit//members") @auth_required() def manage_admin_unit_members(id): admin_unit = get_admin_unit_for_manage_or_404(id) - if not has_access(admin_unit, 'admin_unit.members:read'): - return permission_missing(url_for('manage_admin_unit', id=id)) + if not has_access(admin_unit, "admin_unit.members:read"): + return permission_missing(url_for("manage_admin_unit", id=id)) - members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == admin_unit.id).order_by(func.lower(User.email)).paginate() - invitations = AdminUnitMemberInvitation.query.filter(AdminUnitMemberInvitation.admin_unit_id == admin_unit.id).order_by(func.lower(AdminUnitMemberInvitation.email)).all() + members = ( + AdminUnitMember.query.join(User) + .filter(AdminUnitMember.admin_unit_id == admin_unit.id) + .order_by(func.lower(User.email)) + .paginate() + ) + invitations = ( + AdminUnitMemberInvitation.query.filter( + AdminUnitMemberInvitation.admin_unit_id == admin_unit.id + ) + .order_by(func.lower(AdminUnitMemberInvitation.email)) + .all() + ) - return render_template('manage/members.html', + return render_template( + "manage/members.html", admin_unit=admin_unit, - can_invite_users=has_access(admin_unit, 'admin_unit.members:invite'), + can_invite_users=has_access(admin_unit, "admin_unit.members:invite"), members=members.items, invitations=invitations, - pagination=get_pagination_urls(members, id=id)) + pagination=get_pagination_urls(members, id=id), + ) -@app.route('/manage/admin_unit//widgets', methods=('GET', 'POST')) + +@app.route("/manage/admin_unit//widgets", methods=("GET", "POST")) @auth_required() def manage_admin_unit_widgets(id): admin_unit = get_admin_unit_for_manage_or_404(id) - default_background_color = '#ffffff' - default_primary_color = '#007bff' + default_background_color = "#ffffff" + default_primary_color = "#007bff" form = UpdateAdminUnitWidgetForm(obj=admin_unit) @@ -154,8 +228,8 @@ def manage_admin_unit_widgets(id): form.widget_link_color.data = default_primary_color if form.validate_on_submit(): - if not has_access(admin_unit, 'admin_unit:update'): - return permission_missing(url_for('manage_admin_unit', id=admin_unit.id)) + if not has_access(admin_unit, "admin_unit:update"): + return permission_missing(url_for("manage_admin_unit", id=admin_unit.id)) form.populate_obj(admin_unit) @@ -170,14 +244,12 @@ def manage_admin_unit_widgets(id): try: db.session.commit() - flash(gettext('Settings successfully updated'), 'success') - return redirect(url_for('manage_admin_unit_widgets', id=admin_unit.id)) + flash(gettext("Settings successfully updated"), "success") + return redirect(url_for("manage_admin_unit_widgets", id=admin_unit.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('manage/widgets.html', - form=form, - admin_unit=admin_unit) \ No newline at end of file + return render_template("manage/widgets.html", form=form, admin_unit=admin_unit) diff --git a/project/views/organizer.py b/project/views/organizer.py index 69c4041..a443ce4 100644 --- a/project/views/organizer.py +++ b/project/views/organizer.py @@ -1,19 +1,26 @@ from project import app, db from project.models import EventOrganizer, Location -from flask import render_template, flash, url_for, redirect, request, jsonify +from flask import render_template, flash, url_for, redirect from flask_babelex import gettext from flask_security import auth_required -from project.access import has_access, access_or_401, get_admin_unit_for_manage_or_404 -from project.forms.organizer import CreateOrganizerForm, UpdateOrganizerForm, DeleteOrganizerForm -from project.views.utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError -from sqlalchemy.sql import asc, func +from project.access import access_or_401, get_admin_unit_for_manage_or_404 +from project.forms.organizer import ( + CreateOrganizerForm, + UpdateOrganizerForm, + DeleteOrganizerForm, +) +from project.views.utils import ( + flash_errors, + handleSqlError, +) from sqlalchemy.exc import SQLAlchemyError -@app.route('/manage/admin_unit//organizers/create', methods=('GET', 'POST')) + +@app.route("/manage/admin_unit//organizers/create", methods=("GET", "POST")) @auth_required() def manage_admin_unit_organizer_create(id): admin_unit = get_admin_unit_for_manage_or_404(id) - access_or_401(admin_unit, 'organizer:create') + access_or_401(admin_unit, "organizer:create") form = CreateOrganizerForm() @@ -26,18 +33,21 @@ def manage_admin_unit_organizer_create(id): try: db.session.add(organizer) db.session.commit() - flash(gettext('Organizer successfully created'), 'success') - return redirect(url_for('manage_admin_unit_organizers', id=organizer.admin_unit_id)) + flash(gettext("Organizer successfully created"), "success") + return redirect( + url_for("manage_admin_unit_organizers", id=organizer.admin_unit_id) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') - return render_template('organizer/create.html', form=form) + flash(handleSqlError(e), "danger") + return render_template("organizer/create.html", form=form) -@app.route('/organizer//update', methods=('GET', 'POST')) + +@app.route("/organizer//update", methods=("GET", "POST")) @auth_required() def organizer_update(id): organizer = EventOrganizer.query.get_or_404(id) - access_or_401(organizer.adminunit, 'organizer:update') + access_or_401(organizer.adminunit, "organizer:update") form = UpdateOrganizerForm(obj=organizer) @@ -46,42 +56,44 @@ def organizer_update(id): try: db.session.commit() - flash(gettext('Organizer successfully updated'), 'success') - return redirect(url_for('manage_admin_unit_organizers', id=organizer.admin_unit_id)) + flash(gettext("Organizer successfully updated"), "success") + return redirect( + url_for("manage_admin_unit_organizers", id=organizer.admin_unit_id) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") - return render_template('organizer/update.html', - form=form, - organizer=organizer) + return render_template("organizer/update.html", form=form, organizer=organizer) -@app.route('/organizer//delete', methods=('GET', 'POST')) + +@app.route("/organizer//delete", methods=("GET", "POST")) @auth_required() def organizer_delete(id): organizer = EventOrganizer.query.get_or_404(id) - access_or_401(organizer.adminunit, 'organizer:delete') + access_or_401(organizer.adminunit, "organizer:delete") form = DeleteOrganizerForm() if form.validate_on_submit(): if form.name.data != organizer.name: - flash(gettext('Entered name does not match organizer name'), 'danger') + flash(gettext("Entered name does not match organizer name"), "danger") else: try: db.session.delete(organizer) db.session.commit() - flash(gettext('Organizer successfully deleted'), 'success') - return redirect(url_for('manage_admin_unit_organizers', id=organizer.admin_unit_id)) + flash(gettext("Organizer successfully deleted"), "success") + return redirect( + url_for("manage_admin_unit_organizers", id=organizer.admin_unit_id) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('organizer/delete.html', - form=form, - organizer=organizer) + return render_template("organizer/delete.html", form=form, organizer=organizer) + def update_organizer_with_form(organizer, form): - form.populate_obj(organizer) \ No newline at end of file + form.populate_obj(organizer) diff --git a/project/views/planing.py b/project/views/planing.py index 80b91aa..59558f2 100644 --- a/project/views/planing.py +++ b/project/views/planing.py @@ -1,21 +1,14 @@ -from project import app, db -from project.models import Event, EventDate, EventReviewStatus -from flask import render_template, flash, url_for, redirect, request -from flask_babelex import gettext -from project.dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date -from dateutil.relativedelta import relativedelta -from project.views.utils import flash_errors, track_analytics, get_pagination_urls -from sqlalchemy import and_, or_, not_ -import json -from project.jsonld import get_sd_for_event_date, DateTimeEncoder +from project import app +from flask import render_template, request from project.services.event_search import EventSearchParams -from project.services.event import get_event_dates_query from project.forms.planing import PlaningForm from project.views.event import get_event_category_choices + def prepare_event_date_form(form): form.category_id.choices = get_event_category_choices() - form.category_id.choices.insert(0, (0, '')) + form.category_id.choices.insert(0, (0, "")) + @app.route("/planing") def planing(): @@ -25,6 +18,4 @@ def planing(): form = PlaningForm(formdata=request.args, obj=params) prepare_event_date_form(form) - return render_template('planing/list.html', - form=form, - params=params) \ No newline at end of file + return render_template("planing/list.html", form=form, params=params) diff --git a/project/views/reference.py b/project/views/reference.py index 1f8263e..1606cb5 100644 --- a/project/views/reference.py +++ b/project/views/reference.py @@ -1,7 +1,14 @@ from project import app, db from project.views.utils import get_pagination_urls, flash_errors, handleSqlError -from project.access import get_admin_unit_for_manage_or_404, get_admin_units_for_event_reference -from project.forms.reference import CreateEventReferenceForm, UpdateEventReferenceForm, DeleteReferenceForm +from project.access import ( + get_admin_unit_for_manage_or_404, + get_admin_units_for_event_reference, +) +from project.forms.reference import ( + CreateEventReferenceForm, + UpdateEventReferenceForm, + DeleteReferenceForm, +) from flask import render_template, flash, redirect, url_for, abort from flask_babelex import gettext from flask_security import auth_required @@ -10,7 +17,8 @@ from project.access import access_or_401, can_reference_event from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.sql import desc -@app.route('/event//reference', methods=('GET', 'POST')) + +@app.route("/event//reference", methods=("GET", "POST")) def event_reference(event_id): event = Event.query.get_or_404(event_id) user_can_reference_event = can_reference_event(event) @@ -19,7 +27,13 @@ def event_reference(event_id): abort(401) form = CreateEventReferenceForm() - form.admin_unit_id.choices = sorted([(admin_unit.id, admin_unit.name) for admin_unit in get_admin_units_for_event_reference(event)], key=lambda admin_unit: admin_unit[1]) + form.admin_unit_id.choices = sorted( + [ + (admin_unit.id, admin_unit.name) + for admin_unit in get_admin_units_for_event_reference(event) + ], + key=lambda admin_unit: admin_unit[1], + ) if form.validate_on_submit(): reference = EventReference() @@ -29,22 +43,21 @@ def event_reference(event_id): try: db.session.add(reference) db.session.commit() - flash(gettext('Event successfully referenced'), 'success') - return redirect(url_for('event', event_id=event.id)) + flash(gettext("Event successfully referenced"), "success") + return redirect(url_for("event", event_id=event.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('event/reference.html', - form=form, - event=event) + return render_template("event/reference.html", form=form, event=event) -@app.route('/reference//update', methods=('GET', 'POST')) + +@app.route("/reference//update", methods=("GET", "POST")) def event_reference_update(id): reference = EventReference.query.get_or_404(id) - access_or_401(reference.admin_unit, 'reference:update') + access_or_401(reference.admin_unit, "reference:update") form = UpdateEventReferenceForm(obj=reference) @@ -53,62 +66,83 @@ def event_reference_update(id): try: db.session.commit() - flash(gettext('Reference successfully updated'), 'success') - return redirect(url_for('manage_admin_unit_references_incoming', id=reference.admin_unit_id)) + flash(gettext("Reference successfully updated"), "success") + return redirect( + url_for( + "manage_admin_unit_references_incoming", id=reference.admin_unit_id + ) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('reference/update.html', - form=form, - reference=reference) + return render_template("reference/update.html", form=form, reference=reference) -@app.route('/manage/admin_unit//references/incoming') + +@app.route("/manage/admin_unit//references/incoming") @auth_required() def manage_admin_unit_references_incoming(id): admin_unit = get_admin_unit_for_manage_or_404(id) - references = EventReference.query.filter(EventReference.admin_unit_id == admin_unit.id).order_by(desc(EventReference.created_at)).paginate() + references = ( + EventReference.query.filter(EventReference.admin_unit_id == admin_unit.id) + .order_by(desc(EventReference.created_at)) + .paginate() + ) - return render_template('manage/references_incoming.html', + return render_template( + "manage/references_incoming.html", admin_unit=admin_unit, references=references.items, - pagination=get_pagination_urls(references, id=id)) + pagination=get_pagination_urls(references, id=id), + ) -@app.route('/manage/admin_unit//references/outgoing') + +@app.route("/manage/admin_unit//references/outgoing") @auth_required() def manage_admin_unit_references_outgoing(id): admin_unit = get_admin_unit_for_manage_or_404(id) - references = EventReference.query.join(Event).filter(Event.admin_unit_id == admin_unit.id).order_by(desc(EventReference.created_at)).paginate() + references = ( + EventReference.query.join(Event) + .filter(Event.admin_unit_id == admin_unit.id) + .order_by(desc(EventReference.created_at)) + .paginate() + ) - return render_template('manage/references_outgoing.html', + return render_template( + "manage/references_outgoing.html", admin_unit=admin_unit, references=references.items, - pagination=get_pagination_urls(references, id=id)) + pagination=get_pagination_urls(references, id=id), + ) -@app.route('/reference//delete', methods=('GET', 'POST')) + +@app.route("/reference//delete", methods=("GET", "POST")) def reference_delete(id): reference = EventReference.query.get_or_404(id) - access_or_401(reference.admin_unit, 'reference:delete') + access_or_401(reference.admin_unit, "reference:delete") form = DeleteReferenceForm() if form.validate_on_submit(): if form.name.data != reference.event.name: - flash(gettext('Entered name does not match event name'), 'danger') + flash(gettext("Entered name does not match event name"), "danger") else: try: db.session.delete(reference) db.session.commit() - flash(gettext('Reference successfully deleted'), 'success') - return redirect(url_for('manage_admin_unit_references_incoming', id=reference.admin_unit_id)) + flash(gettext("Reference successfully deleted"), "success") + return redirect( + url_for( + "manage_admin_unit_references_incoming", + id=reference.admin_unit_id, + ) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('reference/delete.html', - form=form, - reference=reference) \ No newline at end of file + return render_template("reference/delete.html", form=form, reference=reference) diff --git a/project/views/reference_request.py b/project/views/reference_request.py index a014123..eec2dd8 100644 --- a/project/views/reference_request.py +++ b/project/views/reference_request.py @@ -1,45 +1,79 @@ from project import app, db -from project.views.utils import get_pagination_urls, flash_errors, handleSqlError, send_mail -from project.forms.reference_request import CreateEventReferenceRequestForm, DeleteReferenceRequestForm +from project.views.utils import ( + get_pagination_urls, + flash_errors, + handleSqlError, + send_mail, +) +from project.forms.reference_request import CreateEventReferenceRequestForm from flask import render_template, flash, redirect, url_for from flask_babelex import gettext from flask_security import auth_required -from project.models import EventReferenceRequest, Event, AdminUnit, AdminUnitMember, User, EventReferenceRequestReviewStatus -from project.access import access_or_401, get_admin_unit_for_manage_or_404, has_admin_unit_member_permission +from project.models import ( + EventReferenceRequest, + Event, + AdminUnit, + AdminUnitMember, + User, + EventReferenceRequestReviewStatus, +) +from project.access import ( + access_or_401, + get_admin_unit_for_manage_or_404, + has_admin_unit_member_permission, +) from sqlalchemy.exc import SQLAlchemyError -from sqlalchemy import and_, or_, not_ from sqlalchemy.sql import desc from project.services.reference import get_reference_requests_incoming_query -@app.route('/manage/admin_unit//reference_requests/incoming') + +@app.route("/manage/admin_unit//reference_requests/incoming") @auth_required() def manage_admin_unit_reference_requests_incoming(id): admin_unit = get_admin_unit_for_manage_or_404(id) - requests = get_reference_requests_incoming_query(admin_unit).order_by(desc(EventReferenceRequest.created_at)).paginate() + requests = ( + get_reference_requests_incoming_query(admin_unit) + .order_by(desc(EventReferenceRequest.created_at)) + .paginate() + ) - return render_template('manage/reference_requests_incoming.html', + return render_template( + "manage/reference_requests_incoming.html", admin_unit=admin_unit, requests=requests.items, - pagination=get_pagination_urls(requests, id=id)) + pagination=get_pagination_urls(requests, id=id), + ) -@app.route('/manage/admin_unit//reference_requests/outgoing') + +@app.route("/manage/admin_unit//reference_requests/outgoing") @auth_required() def manage_admin_unit_reference_requests_outgoing(id): admin_unit = get_admin_unit_for_manage_or_404(id) - requests = EventReferenceRequest.query.join(Event).filter(Event.admin_unit_id == admin_unit.id).order_by(desc(EventReferenceRequest.created_at)).paginate() + requests = ( + EventReferenceRequest.query.join(Event) + .filter(Event.admin_unit_id == admin_unit.id) + .order_by(desc(EventReferenceRequest.created_at)) + .paginate() + ) - return render_template('manage/reference_requests_outgoing.html', + return render_template( + "manage/reference_requests_outgoing.html", admin_unit=admin_unit, requests=requests.items, - pagination=get_pagination_urls(requests, id=id)) + pagination=get_pagination_urls(requests, id=id), + ) -@app.route('/event//reference_request/create', methods=('GET', 'POST')) + +@app.route("/event//reference_request/create", methods=("GET", "POST")) def event_reference_request_create(event_id): event = Event.query.get_or_404(event_id) - access_or_401(event.admin_unit, 'reference_request:create') + access_or_401(event.admin_unit, "reference_request:create") form = CreateEventReferenceRequestForm() - form.admin_unit_id.choices = sorted([(admin_unit.id, admin_unit.name) for admin_unit in AdminUnit.query.all()], key=lambda admin_unit: admin_unit[1]) + form.admin_unit_id.choices = sorted( + [(admin_unit.id, admin_unit.name) for admin_unit in AdminUnit.query.all()], + key=lambda admin_unit: admin_unit[1], + ) if form.validate_on_submit(): request = EventReferenceRequest() @@ -51,25 +85,30 @@ def event_reference_request_create(event_id): db.session.add(request) db.session.commit() send_reference_request_inbox_mails(request) - flash(gettext('Request successfully created'), 'success') - return redirect(url_for('event', event_id=event.id)) + flash(gettext("Request successfully created"), "success") + return redirect(url_for("event", event_id=event.id)) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('event/reference_request.html', - form=form, - event=event) + return render_template("event/reference_request.html", form=form, event=event) + def send_reference_request_inbox_mails(request): # Benachrichtige alle Mitglieder der AdminUnit, die diesen Request verifizieren können - members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == request.admin_unit_id).all() + members = ( + AdminUnitMember.query.join(User) + .filter(AdminUnitMember.admin_unit_id == request.admin_unit_id) + .all() + ) for member in members: - if has_admin_unit_member_permission(member, 'reference_request:verify'): - send_mail(member.user.email, - gettext('New reference request'), - 'reference_request_notice', - request=request) + if has_admin_unit_member_permission(member, "reference_request:verify"): + send_mail( + member.user.email, + gettext("New reference request"), + "reference_request_notice", + request=request, + ) diff --git a/project/views/reference_request_review.py b/project/views/reference_request_review.py index 65a0e4b..83f63c5 100644 --- a/project/views/reference_request_review.py +++ b/project/views/reference_request_review.py @@ -1,23 +1,38 @@ from project import app, db -from project.models import Event, EventDate, EventReferenceRequest, EventReferenceRequestReviewStatus, AdminUnitMember, User +from project.models import ( + EventDate, + EventReferenceRequest, + EventReferenceRequestReviewStatus, + AdminUnitMember, + User, +) from flask import render_template, flash, url_for, redirect, abort from flask_babelex import gettext -from flask_security import auth_required -from project.access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission +from project.access import ( + has_access, + access_or_401, + has_admin_unit_member_permission, +) from project.dateutils import today from project.forms.reference_request import ReferenceRequestReviewForm from project.views.utils import flash_errors, send_mail, handleSqlError from project.services.reference import create_event_reference_for_request from sqlalchemy.exc import SQLAlchemyError -@app.route('/reference_request//review', methods=('GET', 'POST')) + +@app.route("/reference_request//review", methods=("GET", "POST")) def event_reference_request_review(id): request = EventReferenceRequest.query.get_or_404(id) - access_or_401(request.admin_unit, 'reference_request:verify') + access_or_401(request.admin_unit, "reference_request:verify") if request.review_status == EventReferenceRequestReviewStatus.verified: - flash(gettext('Request already verified'), 'danger') - return redirect(url_for('manage_admin_unit_reference_requests_incoming', id=request.admin_unit_id)) + flash(gettext("Request already verified"), "danger") + return redirect( + url_for( + "manage_admin_unit_reference_requests_incoming", + id=request.admin_unit_id, + ) + ) form = ReferenceRequestReviewForm(obj=request) @@ -34,45 +49,69 @@ def event_reference_request_review(id): if request.review_status == EventReferenceRequestReviewStatus.verified: reference = create_event_reference_for_request(request) reference.rating = form.rating.data - msg = gettext('Request successfully updated') + msg = gettext("Request successfully updated") else: - msg = gettext('Reference successfully created') + msg = gettext("Reference successfully created") db.session.commit() send_reference_request_review_status_mails(request) - flash(msg, 'success') - return redirect(url_for('manage_admin_unit_reference_requests_incoming', id=request.admin_unit_id)) + flash(msg, "success") + return redirect( + url_for( + "manage_admin_unit_reference_requests_incoming", + id=request.admin_unit_id, + ) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - dates = EventDate.query.with_parent(request.event).filter(EventDate.start >= today).order_by(EventDate.start).all() - return render_template('reference_request/review.html', + dates = ( + EventDate.query.with_parent(request.event) + .filter(EventDate.start >= today) + .order_by(EventDate.start) + .all() + ) + return render_template( + "reference_request/review.html", form=form, dates=dates, request=request, - event=request.event) + event=request.event, + ) -@app.route('/reference_request//review_status') + +@app.route("/reference_request//review_status") def event_reference_request_review_status(id): request = EventReferenceRequest.query.get_or_404(id) - if not has_access(request.admin_unit, 'reference_request:verify') and not has_access(request.event.admin_unit, 'reference_request:create'): + if not has_access( + request.admin_unit, "reference_request:verify" + ) and not has_access(request.event.admin_unit, "reference_request:create"): abort(401) - return render_template('reference_request/review_status.html', + return render_template( + "reference_request/review_status.html", reference_request=request, - event=request.event) + event=request.event, + ) + def send_reference_request_review_status_mails(request): # Benachrichtige alle Mitglieder der AdminUnit, die diesen Request erstellt hatte - members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == request.event.admin_unit_id).all() + members = ( + AdminUnitMember.query.join(User) + .filter(AdminUnitMember.admin_unit_id == request.event.admin_unit_id) + .all() + ) for member in members: - if has_admin_unit_member_permission(member, 'reference_request:create'): - send_mail(member.user.email, - gettext('Event review status updated'), - 'reference_request_review_status_notice', - request=request) + if has_admin_unit_member_permission(member, "reference_request:create"): + send_mail( + member.user.email, + gettext("Event review status updated"), + "reference_request_review_status_notice", + request=request, + ) diff --git a/project/views/root.py b/project/views/root.py index 61d389b..4c52fb1 100644 --- a/project/views/root.py +++ b/project/views/root.py @@ -2,26 +2,31 @@ from project import app from project.views.utils import track_analytics from flask import url_for, render_template, request, redirect + @app.route("/") def home(): - if 'src' in request.args: - track_analytics("home", '', request.args['src']) - return redirect(url_for('home')) + if "src" in request.args: + track_analytics("home", "", request.args["src"]) + return redirect(url_for("home")) + + return render_template("home.html") - return render_template('home.html') @app.route("/example") def example(): - return render_template('example.html') + return render_template("example.html") + @app.route("/impressum") def impressum(): - return render_template('impressum.html') + return render_template("impressum.html") + @app.route("/datenschutz") def datenschutz(): - return render_template('datenschutz.html') + return render_template("datenschutz.html") + @app.route("/developer") def developer(): - return render_template('developer/read.html') \ No newline at end of file + return render_template("developer/read.html") diff --git a/project/views/user.py b/project/views/user.py index 99deee4..ec6efdf 100644 --- a/project/views/user.py +++ b/project/views/user.py @@ -3,12 +3,15 @@ from project.models import AdminUnitMember, AdminUnitMemberInvitation from flask import render_template from flask_security import auth_required, current_user + @app.route("/profile") @auth_required() def profile(): - admin_unit_members = AdminUnitMember.query.filter_by(user_id = current_user.id).all() - invitations = AdminUnitMemberInvitation.query.filter(AdminUnitMemberInvitation.email == current_user.email).all() + admin_unit_members = AdminUnitMember.query.filter_by(user_id=current_user.id).all() + invitations = AdminUnitMemberInvitation.query.filter( + AdminUnitMemberInvitation.email == current_user.email + ).all() - return render_template('profile.html', - admin_unit_members=admin_unit_members, - invitations=invitations) \ No newline at end of file + return render_template( + "profile.html", admin_unit_members=admin_unit_members, invitations=invitations + ) diff --git a/project/views/utils.py b/project/views/utils.py index bad88e8..4138cdf 100644 --- a/project/views/utils.py +++ b/project/views/utils.py @@ -4,8 +4,9 @@ from flask_babelex import gettext from flask import request, url_for, render_template, flash, redirect, Markup from flask_mail import Message + def track_analytics(key, value1, value2): - result = Analytics(key = key, value1 = value1) + result = Analytics(key=key, value1=value1) if value2 is not None: result.value2 = value2 @@ -15,12 +16,14 @@ def track_analytics(key, value1, value2): return result + def handleSqlError(e): - message = str(e.__dict__['orig']) + message = str(e.__dict__["orig"]) print(message) return message -def upsert_image_with_data(image, data, encoding_format = "image/jpeg"): + +def upsert_image_with_data(image, data, encoding_format="image/jpeg"): if image is None: image = Image() @@ -29,6 +32,7 @@ def upsert_image_with_data(image, data, encoding_format = "image/jpeg"): return image + def get_pagination_urls(pagination, **kwargs): result = {} @@ -47,28 +51,34 @@ def get_pagination_urls(pagination, **kwargs): return result + def flash_errors(form): for field, errors in form.errors.items(): for error in errors: - flash(gettext("Error in the %s field - %s") % ( - getattr(form, field).label.text, - error - ), 'danger') + flash( + gettext("Error in the %s field - %s") + % (getattr(form, field).label.text, error), + "danger", + ) -def flash_message(msg, url, link_text = None, category = 'success'): + +def flash_message(msg, url, link_text=None, category="success"): if not link_text: - link_text = gettext('Show') + link_text = gettext("Show") link = ' – %s' % (url, link_text) message = Markup(msg + link) flash(message, category) + def permission_missing(redirect_location): - flash('You do not have permission for this action', 'danger') + flash("You do not have permission for this action", "danger") return redirect(redirect_location) + def send_mail(recipient, subject, template, **context): send_mails([recipient], subject, template, **context) + def send_mails(recipients, subject, template, **context): msg = Message(subject) msg.recipients = recipients @@ -80,4 +90,4 @@ def send_mails(recipients, subject, template, **context): print(msg.body) return - mail.send(msg) \ No newline at end of file + mail.send(msg) diff --git a/project/views/widget.py b/project/views/widget.py index ab15c47..995e8d8 100644 --- a/project/views/widget.py +++ b/project/views/widget.py @@ -1,17 +1,28 @@ from project import app, db -from project.models import User, EventDate, Event, AdminUnit, EventOrganizer, EventSuggestion, EventReviewStatus, AdminUnitMember -from project.dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date -from dateutil.relativedelta import relativedelta +from project.models import ( + User, + EventDate, + AdminUnit, + EventOrganizer, + EventSuggestion, + EventReviewStatus, + AdminUnitMember, +) from flask import render_template, request, flash, redirect, url_for from flask_babelex import gettext -from flask_security import auth_required, current_user -from sqlalchemy import and_, or_, not_ -from sqlalchemy.sql import asc, func +from flask_security import current_user +from sqlalchemy.sql import func from sqlalchemy.exc import SQLAlchemyError from project.services.event import get_event_dates_query from project.services.event_search import EventSearchParams from project.services.place import get_event_places -from project.views.utils import get_pagination_urls, flash_errors, flash_message, send_mail, handleSqlError +from project.views.utils import ( + get_pagination_urls, + flash_errors, + flash_message, + send_mail, + handleSqlError, +) import json from project.jsonld import DateTimeEncoder, get_sd_for_event_date from project.forms.event_date import FindEventDateForm @@ -19,9 +30,12 @@ from project.forms.event_suggestion import CreateEventSuggestionForm from project.views.event_date import prepare_event_date_form from project.access import has_admin_unit_member_permission + @app.route("//widget/eventdates") def widget_event_dates(au_short_name): - admin_unit = AdminUnit.query.filter(AdminUnit.short_name == au_short_name).first_or_404() + admin_unit = AdminUnit.query.filter( + AdminUnit.short_name == au_short_name + ).first_or_404() params = EventSearchParams() params.set_default_date_range() @@ -35,27 +49,39 @@ def widget_event_dates(au_short_name): params.admin_unit_id = admin_unit.id dates = get_event_dates_query(params).paginate() - return render_template('widget/event_date/list.html', + return render_template( + "widget/event_date/list.html", form=form, styles=get_styles(admin_unit), admin_unit=admin_unit, params=params, dates=dates.items, - pagination=get_pagination_urls(dates, au_short_name=au_short_name)) + pagination=get_pagination_urls(dates, au_short_name=au_short_name), + ) -@app.route('//widget/eventdate/') + +@app.route("//widget/eventdate/") def widget_event_date(au_short_name, id): - admin_unit = AdminUnit.query.filter(AdminUnit.short_name == au_short_name).first_or_404() + admin_unit = AdminUnit.query.filter( + AdminUnit.short_name == au_short_name + ).first_or_404() event_date = EventDate.query.get_or_404(id) - structured_data = json.dumps(get_sd_for_event_date(event_date), indent=2, cls=DateTimeEncoder) - return render_template('widget/event_date/read.html', + structured_data = json.dumps( + get_sd_for_event_date(event_date), indent=2, cls=DateTimeEncoder + ) + return render_template( + "widget/event_date/read.html", event_date=event_date, styles=get_styles(admin_unit), - structured_data=structured_data) + structured_data=structured_data, + ) + @app.route("//widget/infoscreen") def widget_infoscreen(au_short_name): - admin_unit = AdminUnit.query.filter(AdminUnit.short_name == au_short_name).first_or_404() + admin_unit = AdminUnit.query.filter( + AdminUnit.short_name == au_short_name + ).first_or_404() params = EventSearchParams() params.load_from_request() @@ -63,24 +89,36 @@ def widget_infoscreen(au_short_name): dates = get_event_dates_query(params).paginate(max_per_page=5) - return render_template('widget/infoscreen/read.html', + return render_template( + "widget/infoscreen/read.html", admin_unit=admin_unit, params=params, styles=get_styles(admin_unit), - dates=dates.items) + dates=dates.items, + ) -@app.route("//widget/event_suggestions/create", methods=('GET', 'POST')) + +@app.route( + "//widget/event_suggestions/create", methods=("GET", "POST") +) def event_suggestion_create_for_admin_unit(au_short_name): - admin_unit = AdminUnit.query.filter(AdminUnit.short_name == au_short_name).first_or_404() + admin_unit = AdminUnit.query.filter( + AdminUnit.short_name == au_short_name + ).first_or_404() form = CreateEventSuggestionForm() - form.organizer_id.choices = [(o.id, o.name) for o in EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name))] + form.organizer_id.choices = [ + (o.id, o.name) + for o in EventOrganizer.query.filter( + EventOrganizer.admin_unit_id == admin_unit.id + ).order_by(func.lower(EventOrganizer.name)) + ] places = get_event_places(admin_unit.id) form.event_place_id.choices = [(p.id, p.name) for p in places] - form.organizer_id.choices.insert(0, ('', '')) - form.event_place_id.choices.insert(0, ('', '')) + form.organizer_id.choices.insert(0, ("", "")) + form.event_place_id.choices.insert(0, ("", "")) if form.validate_on_submit(): event_suggestion = EventSuggestion() @@ -93,21 +131,36 @@ def event_suggestion_create_for_admin_unit(au_short_name): db.session.commit() send_event_inbox_mails(admin_unit, event_suggestion) - flash(gettext('Thank you so much! The event is being verified.'), 'success') + flash(gettext("Thank you so much! The event is being verified."), "success") if not current_user.is_authenticated: - flash_message(gettext('For more options and your own calendar of events, you can register for free.'), url_for('security.register'), gettext('Register for free'), 'info') + flash_message( + gettext( + "For more options and your own calendar of events, you can register for free." + ), + url_for("security.register"), + gettext("Register for free"), + "info", + ) - return redirect(url_for('event_suggestion_review_status', event_suggestion_id=event_suggestion.id)) + return redirect( + url_for( + "event_suggestion_review_status", + event_suggestion_id=event_suggestion.id, + ) + ) except SQLAlchemyError as e: db.session.rollback() - flash(handleSqlError(e), 'danger') + flash(handleSqlError(e), "danger") else: flash_errors(form) - return render_template('widget/event_suggestion/create.html', + return render_template( + "widget/event_suggestion/create.html", form=form, admin_unit=admin_unit, - styles=get_styles(admin_unit)) + styles=get_styles(admin_unit), + ) + def get_styles(admin_unit): styles = dict() @@ -126,12 +179,19 @@ def get_styles(admin_unit): return styles + def send_event_inbox_mails(admin_unit, event_suggestion): - members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == admin_unit.id).all() + members = ( + AdminUnitMember.query.join(User) + .filter(AdminUnitMember.admin_unit_id == admin_unit.id) + .all() + ) for member in members: - if has_admin_unit_member_permission(member, 'event:verify'): - send_mail(member.user.email, - gettext('New event review'), - 'review_notice', - event_suggestion=event_suggestion) \ No newline at end of file + if has_admin_unit_member_permission(member, "event:verify"): + send_mail( + member.user.email, + gettext("New event review"), + "review_notice", + event_suggestion=event_suggestion, + ) diff --git a/requirements.txt b/requirements.txt index 176857a..90d131c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,17 +1,26 @@ alembic==1.4.2 +appdirs==1.4.4 attrs==20.3.0 Babel==2.8.0 bcrypt==3.1.7 beautifulsoup4==4.9.1 +black==20.8b1 blinker==1.4 certifi==2020.6.20 cffi==1.14.0 +cfgv==3.2.0 chardet==3.0.4 click==7.1.2 colour==0.1.5 +coverage==5.3 +coveralls==2.1.2 +distlib==0.3.1 dnspython==1.16.0 +docopt==0.6.2 dominate==2.5.1 email-validator==1.1.1 +filelock==3.0.12 +flake8==3.8.4 Flask==1.1.2 Flask-BabelEx==0.9.4 Flask-Bootstrap==3.3.7.1 @@ -28,6 +37,7 @@ Flask-SQLAlchemy==2.4.3 Flask-WTF==0.14.3 GeoAlchemy2==0.8.4 gunicorn==20.0.4 +identify==1.5.9 idna==2.9 importlib-metadata==2.0.0 iniconfig==1.1.1 @@ -35,21 +45,31 @@ itsdangerous==1.1.0 Jinja2==2.11.2 Mako==1.1.3 MarkupSafe==1.1.1 +mccabe==0.6.1 +mypy-extensions==0.4.3 +nodeenv==1.5.0 oauthlib==3.1.0 packaging==20.4 passlib==1.7.2 +pathspec==0.8.1 Pillow==7.2.0 pluggy==0.13.1 +pre-commit==2.8.2 psycopg2-binary==2.8.5 py==1.9.0 +pycodestyle==2.6.0 pycparser==2.20 +pyflakes==2.2.0 pyparsing==2.4.7 pytest==6.1.2 +pytest-cov==2.10.1 python-dateutil==2.8.1 python-dotenv==0.13.0 python-editor==1.0.4 pytz==2020.1 +PyYAML==5.3.1 qrcode==6.1 +regex==2020.11.13 requests==2.24.0 requests-oauthlib==1.3.0 six==1.15.0 @@ -58,8 +78,11 @@ speaklater==1.3 SQLAlchemy==1.3.17 SQLAlchemy-Utils==0.36.6 toml==0.10.2 +typed-ast==1.4.1 +typing-extensions==3.7.4.3 urllib3==1.25.9 URLObject==2.4.3 +virtualenv==20.1.0 visitor==0.1.3 Werkzeug==1.0.1 WTForms==2.3.1 diff --git a/runtime.txt b/runtime.txt index 257b314..050dcb9 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.7.6 \ No newline at end of file +python-3.7.9 \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 6892eec..be756b9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,12 +1,15 @@ import pytest import os + def pytest_generate_tests(metafunc): os.environ["DATABASE_URL"] = "postgresql://postgres@localhost/gsevpt_tests" + @pytest.fixture def client(): from project import app, db + app.config["TESTING"] = True app.testing = True @@ -14,4 +17,4 @@ def client(): with app.app_context(): db.drop_all() db.create_all() - yield client \ No newline at end of file + yield client diff --git a/tests/test_app.py b/tests/test_app.py index 4636e99..3c015ad 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,5 +1,3 @@ -import pytest - def test_index(client): - response = client.get('/') - assert b'oveda' in response.data \ No newline at end of file + response = client.get("/") + assert b"oveda" in response.data