Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
Mindiell | 8a48b73eae | |
Mindiell | 77d0b98641 | |
Mindiell | 6c6f2d11e8 | |
Mindiell | 6440bab46b | |
Mindiell | 1f19252dcc | |
Mindiell | d33757e754 | |
Mindiell | 3faa1689e7 |
|
@ -0,0 +1,8 @@
|
||||||
|
FLASK_APP=server.py
|
||||||
|
FLASK_ENV=development
|
||||||
|
BABEL_DEFAULT_LOCALE=fr
|
||||||
|
|
||||||
|
BCRYPT_ROUNDS=6
|
||||||
|
SECRET_KEY=blabla
|
||||||
|
SQLALCHEMY_DATABASE_URI=mysql://politikorama:politikorama@localhost/politikorama
|
||||||
|
API_PER_PAGE=30
|
|
@ -12,4 +12,4 @@ api = Api()
|
||||||
babel = Babel()
|
babel = Babel()
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
login_manager = LoginManager()
|
login_manager = LoginManager()
|
||||||
migrate = Migrate()
|
migrate = Migrate(compare_type=True)
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
from app.controller.admin.importer import (ImportAddressView, ImportContactView,
|
from app.controller.admin.country import ImportCountryView
|
||||||
ImportCountryView, ImportDecisionView, ImportEntityView, ImportMatterView,
|
from app.controller.admin.entity import ImportEntityView
|
||||||
ImportMembershipView, ImportRecommendationView, ImportRepresentativeView,
|
from app.controller.admin.membership import ImportMembershipView
|
||||||
ImportRoleView, ImportStanceView, ImportTypeView)
|
from app.controller.admin.representative import ImportRepresentativeView
|
||||||
|
|
||||||
|
|
||||||
admin_routes = (
|
admin_routes = (
|
||||||
(ImportAddressView, "Addresses", "addresses", "Import"),
|
|
||||||
(ImportContactView, "Contacts", "contacts", "Import"),
|
|
||||||
(ImportCountryView, "Countries", "countries", "Import"),
|
(ImportCountryView, "Countries", "countries", "Import"),
|
||||||
(ImportDecisionView, "Decisions", "decisions", "Import"),
|
|
||||||
(ImportEntityView, "Entities", "entities", "Import"),
|
(ImportEntityView, "Entities", "entities", "Import"),
|
||||||
(ImportMatterView, "Matters", "matters", "Import"),
|
|
||||||
(ImportMembershipView, "Memberships", "memberships", "Import"),
|
(ImportMembershipView, "Memberships", "memberships", "Import"),
|
||||||
(ImportRecommendationView, "Recommendations", "recommendations", "Import"),
|
|
||||||
(ImportRepresentativeView, "Representatives", "representatives", "Import"),
|
(ImportRepresentativeView, "Representatives", "representatives", "Import"),
|
||||||
(ImportRoleView, "Roles", "roles", "Import"),
|
|
||||||
(ImportStanceView, "Stances", "stances", "Import"),
|
|
||||||
(ImportTypeView, "Types", "types", "Import"),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from flask import current_app, g, request, redirect, url_for
|
||||||
|
from flask_admin import BaseView, expose
|
||||||
|
from slugify import slugify
|
||||||
|
|
||||||
|
from app.form.admin import ImportForm
|
||||||
|
from app.controller.admin.importer import default_import
|
||||||
|
from app.model.country import CountryModel
|
||||||
|
|
||||||
|
|
||||||
|
class ImportCountryView(BaseView):
|
||||||
|
@expose("/", methods=["GET", "POST"])
|
||||||
|
def index(self):
|
||||||
|
g.what = {
|
||||||
|
"title": "Import countries",
|
||||||
|
"description": "Importing countries will add unknown ones and update"
|
||||||
|
" known ones. If a country is not present in imported file it"
|
||||||
|
" will not be deleted.",
|
||||||
|
"endpoint": "countries.index",
|
||||||
|
"formats": [
|
||||||
|
"File format accepted is CSV (Comma Separated Values).",
|
||||||
|
"First line represents column headers.",
|
||||||
|
"Other lines are values:",
|
||||||
|
"One column MUST be 'name'",
|
||||||
|
"One column COULD be 'alpha_2'",
|
||||||
|
"One column COULD be 'alpha_3'",
|
||||||
|
"One column COULD be 'official_name'",
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"name,alpha_2",
|
||||||
|
"Spain,es",
|
||||||
|
"Germany,DE",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
"name": None,
|
||||||
|
"alpha_2": "optional",
|
||||||
|
"alpha_3": "optional",
|
||||||
|
"official_name": "optional",
|
||||||
|
}
|
||||||
|
reader = default_import(headers)
|
||||||
|
if len(g.errors) == 0 and reader is not None:
|
||||||
|
for row in reader:
|
||||||
|
country = CountryModel.query.filter_by(
|
||||||
|
name=row[headers["name"]],
|
||||||
|
).first()
|
||||||
|
if headers["alpha_2"] is not None:
|
||||||
|
alpha_2 = row[headers["alpha_2"]]
|
||||||
|
else:
|
||||||
|
alpha_2 = None
|
||||||
|
if headers["alpha_3"] is not None:
|
||||||
|
alpha_3 = row[headers["alpha_3"]]
|
||||||
|
else:
|
||||||
|
alpha_3 = None
|
||||||
|
if headers["official_name"] is not None:
|
||||||
|
official_name = row[headers["official_name"]]
|
||||||
|
else:
|
||||||
|
official_name = None
|
||||||
|
if country is None:
|
||||||
|
country = CountryModel(
|
||||||
|
name = row[headers["name"]],
|
||||||
|
slug = slugify(row[headers["name"]]),
|
||||||
|
alpha_2 = alpha_2,
|
||||||
|
alpha_3 = alpha_3,
|
||||||
|
official_state_name = official_name,
|
||||||
|
)
|
||||||
|
g.messages.append(
|
||||||
|
f"{row[headers['name']]} added."
|
||||||
|
)
|
||||||
|
country.save()
|
||||||
|
else:
|
||||||
|
# Mise à jour du pays !
|
||||||
|
pass
|
||||||
|
|
||||||
|
return self.render("admin/import.html")
|
|
@ -0,0 +1,118 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from flask import current_app, g, request, redirect, url_for
|
||||||
|
from flask_admin import BaseView, expose
|
||||||
|
from slugify import slugify
|
||||||
|
|
||||||
|
from app.form.admin import ImportForm
|
||||||
|
from app.controller.admin.importer import default_import
|
||||||
|
from app.model.entity import EntityModel
|
||||||
|
from app.model.type import TypeModel
|
||||||
|
|
||||||
|
|
||||||
|
class ImportEntityView(BaseView):
|
||||||
|
@expose("/", methods=["GET", "POST"])
|
||||||
|
def index(self):
|
||||||
|
g.what = {
|
||||||
|
"title": "Import entities",
|
||||||
|
"description": "Importing entities will add unknown ones and update"
|
||||||
|
" known ones. If an entity is not present in imported file it"
|
||||||
|
" will not be deleted.",
|
||||||
|
"endpoint": "entities.index",
|
||||||
|
"formats": [
|
||||||
|
"File format accepted is CSV (Comma Separated Values).",
|
||||||
|
"First line represents column headers.",
|
||||||
|
"Other lines are values:",
|
||||||
|
"One column MUST be 'name'",
|
||||||
|
"One column MUST be 'reference'",
|
||||||
|
"One column MUST be 'parent_reference'",
|
||||||
|
"One column MUST be 'start'",
|
||||||
|
"One column COULD be 'end'",
|
||||||
|
"One column COULD be 'source'",
|
||||||
|
"One column COULD be 'type_code'",
|
||||||
|
"One column COULD be 'type_name'",
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"name,reference,parent_reference,source,type_code,type_name,start,end",
|
||||||
|
"Thingy Commission,CO1234,NA123,French National Assembly,COMM,Commission,2020-01-01,",
|
||||||
|
"Group Assembly,NA123,,French National Assembly,GROU,Group,2019-01-01,2099-12-31",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
"name": None,
|
||||||
|
"reference": None,
|
||||||
|
"parent_reference": None,
|
||||||
|
"source": "optional",
|
||||||
|
"type_code": "optional",
|
||||||
|
"type_name": "optional",
|
||||||
|
"start": None,
|
||||||
|
"end": "optional",
|
||||||
|
}
|
||||||
|
reader = default_import(headers)
|
||||||
|
if len(g.errors) == 0 and reader is not None:
|
||||||
|
for row in reader:
|
||||||
|
if headers["type_code"] is not None:
|
||||||
|
entity_type = TypeModel.query.filter_by(
|
||||||
|
code=row[headers["type_code"]].upper(),
|
||||||
|
).first()
|
||||||
|
if entity_type is None:
|
||||||
|
entity_type = TypeModel(
|
||||||
|
code=row[headers["type_code"]].upper(),
|
||||||
|
name=row[headers["type_name"]],
|
||||||
|
slug=slugify(row[headers["type_name"]]),
|
||||||
|
)
|
||||||
|
entity_type.save()
|
||||||
|
|
||||||
|
if headers["source"] is not None:
|
||||||
|
source = row[headers["source"]]
|
||||||
|
else:
|
||||||
|
source = None
|
||||||
|
|
||||||
|
if row[headers["start"]] != "":
|
||||||
|
start = datetime.strptime(
|
||||||
|
row[headers["start"]], "%Y-%m-%d"
|
||||||
|
).date()
|
||||||
|
else:
|
||||||
|
start = None
|
||||||
|
|
||||||
|
end = None
|
||||||
|
if headers["end"] is not None:
|
||||||
|
if row[headers["end"]] != "":
|
||||||
|
end = datetime.strptime(
|
||||||
|
row[headers["end"]], "%Y-%m-%d"
|
||||||
|
).date()
|
||||||
|
|
||||||
|
parent = EntityModel.query.filter_by(
|
||||||
|
reference=row[headers["parent_reference"]].upper(),
|
||||||
|
).first()
|
||||||
|
if parent is not None:
|
||||||
|
parent_id = parent.id
|
||||||
|
else:
|
||||||
|
parent_id = None
|
||||||
|
|
||||||
|
entity = EntityModel.query.filter_by(
|
||||||
|
reference=row[headers["reference"]].upper()
|
||||||
|
).first()
|
||||||
|
if entity is None:
|
||||||
|
entity = EntityModel(
|
||||||
|
name = row[headers["name"]],
|
||||||
|
slug = slugify(row[headers["name"]]),
|
||||||
|
reference = row[headers["reference"]].upper(),
|
||||||
|
parent_id = parent_id,
|
||||||
|
source = source,
|
||||||
|
type = entity_type,
|
||||||
|
start = start,
|
||||||
|
end = end,
|
||||||
|
active = True if end is None else False,
|
||||||
|
)
|
||||||
|
g.messages.append(
|
||||||
|
f"{row[headers['name']]} added."
|
||||||
|
)
|
||||||
|
entity.save()
|
||||||
|
else:
|
||||||
|
# updating information ?
|
||||||
|
pass
|
||||||
|
|
||||||
|
return self.render("admin/import.html")
|
|
@ -11,18 +11,7 @@ from slugify import slugify
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
|
|
||||||
from app.form.admin import ImportForm
|
from app.form.admin import ImportForm
|
||||||
from app.model.address import AddressModel
|
from app import model
|
||||||
from app.model.contact import ContactModel
|
|
||||||
from app.model.country import CountryModel
|
|
||||||
from app.model.decision import DecisionModel
|
|
||||||
from app.model.entity import EntityModel
|
|
||||||
from app.model.matter import MatterModel
|
|
||||||
from app.model.membership import MembershipModel
|
|
||||||
from app.model.recommendation import RecommendationModel
|
|
||||||
from app.model.representative import RepresentativeModel
|
|
||||||
from app.model.role import RoleModel
|
|
||||||
from app.model.stance import StanceModel
|
|
||||||
from app.model.type import TypeModel
|
|
||||||
|
|
||||||
|
|
||||||
def default_import(headers):
|
def default_import(headers):
|
||||||
|
@ -91,14 +80,14 @@ class ImportAddressView(BaseView):
|
||||||
}
|
}
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
for row in reader:
|
for row in reader:
|
||||||
address_country = CountryModel.query.filter_by(
|
address_country = model.CountryModel.query.filter_by(
|
||||||
code=row[headers["country_code"]].upper()
|
code=row[headers["country_code"]].upper()
|
||||||
).first()
|
).first()
|
||||||
address = AddressModel.query.filter_by(
|
address = model.AddressModel.query.filter_by(
|
||||||
slug==slugify(row[headers["name"]]),
|
slug==slugify(row[headers["name"]]),
|
||||||
).first()
|
).first()
|
||||||
if address is None:
|
if address is None:
|
||||||
address = AddressModel(
|
address = model.AddressModel(
|
||||||
name = row[headers["name"]],
|
name = row[headers["name"]],
|
||||||
slug = slugify(row[headers["name"]]),
|
slug = slugify(row[headers["name"]]),
|
||||||
country = address_country,
|
country = address_country,
|
||||||
|
@ -195,21 +184,21 @@ class ImportContactView(BaseView):
|
||||||
}
|
}
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
for row in reader:
|
for row in reader:
|
||||||
contact_representative = RepresentativeModel.query.filter_by(
|
contact_representative = model.RepresentativeModel.query.filter_by(
|
||||||
slug=row[headers["representative_slug"]],
|
slug=row[headers["representative_slug"]],
|
||||||
).first()
|
).first()
|
||||||
if headers["addres_slug"] is not None:
|
if headers["addres_slug"] is not None:
|
||||||
contact_address = AddressModel.query.filter_by(
|
contact_address = model.AddressModel.query.filter_by(
|
||||||
slug==row[headers["address_slug"]],
|
slug==row[headers["address_slug"]],
|
||||||
).first()
|
).first()
|
||||||
else:
|
else:
|
||||||
contact_address = None
|
contact_address = None
|
||||||
contact = ContactModel.query.filter_by(
|
contact = model.ContactModel.query.filter_by(
|
||||||
slug==slugify(row[headers["name"]]),
|
slug==slugify(row[headers["name"]]),
|
||||||
representative_id=contact_representative.id,
|
representative_id=contact_representative.id,
|
||||||
).first()
|
).first()
|
||||||
if contact is None:
|
if contact is None:
|
||||||
contact = ContactModel(
|
contact = model.ContactModel(
|
||||||
representative = contact_representative,
|
representative = contact_representative,
|
||||||
address = contact_address,
|
address = contact_address,
|
||||||
name = row[headers["name"]],
|
name = row[headers["name"]],
|
||||||
|
@ -233,52 +222,6 @@ class ImportContactView(BaseView):
|
||||||
return self.render("admin/import.html")
|
return self.render("admin/import.html")
|
||||||
|
|
||||||
|
|
||||||
class ImportCountryView(BaseView):
|
|
||||||
@expose("/", methods=["GET", "POST"])
|
|
||||||
def index(self):
|
|
||||||
headers = {"name": None, "code": None}
|
|
||||||
reader = default_import(headers)
|
|
||||||
g.what = {
|
|
||||||
"title": "Import countries",
|
|
||||||
"description": "Importing countries will add unknown ones and update known"
|
|
||||||
" ones. If a country is not present in imported file it will not be"
|
|
||||||
" deleted.",
|
|
||||||
"endpoint": "countries.index",
|
|
||||||
"formats": [
|
|
||||||
"File format accepted is CSV (Comma Separated Values).",
|
|
||||||
"First line chould be column headers.",
|
|
||||||
"Other lines are values.",
|
|
||||||
"One column MUST be 'name'.",
|
|
||||||
"One column MUST be 'code'.",
|
|
||||||
],
|
|
||||||
"examples": [
|
|
||||||
"name,code",
|
|
||||||
"France,FR",
|
|
||||||
"United States of America,US",
|
|
||||||
"Spain,SP",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
if len(g.errors) == 0 and reader is not None:
|
|
||||||
for row in reader:
|
|
||||||
country = CountryModel.query.filter_by(code=row[headers["code"]]).first()
|
|
||||||
if country is None:
|
|
||||||
country = CountryModel(
|
|
||||||
name = row[headers["name"]],
|
|
||||||
slug = slugify(row[headers["name"]]),
|
|
||||||
code = row[headers["code"]].upper(),
|
|
||||||
)
|
|
||||||
g.messages.append(f"{row[headers['name']]} added.")
|
|
||||||
country.save()
|
|
||||||
else:
|
|
||||||
if country.name != row[headers["name"]]:
|
|
||||||
country.name = row[headers["name"]]
|
|
||||||
country.slug = slugify(row[headers["name"]])
|
|
||||||
g.messages.append(f"{row[headers['name']]} updated.")
|
|
||||||
country.save()
|
|
||||||
|
|
||||||
return self.render("admin/import.html")
|
|
||||||
|
|
||||||
|
|
||||||
class ImportDecisionView(BaseView):
|
class ImportDecisionView(BaseView):
|
||||||
@expose("/", methods=["GET", "POST"])
|
@expose("/", methods=["GET", "POST"])
|
||||||
def index(self):
|
def index(self):
|
||||||
|
@ -311,18 +254,18 @@ class ImportDecisionView(BaseView):
|
||||||
}
|
}
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
for row in reader:
|
for row in reader:
|
||||||
decision_representative = RepresentativeModel.query.filter_by(
|
decision_representative = model.RepresentativeModel.query.filter_by(
|
||||||
slug=row[headers["representative_slug"]],
|
slug=row[headers["representative_slug"]],
|
||||||
).first()
|
).first()
|
||||||
decision_recommendation = RecommendationModel.query.filter_by(
|
decision_recommendation = model.RecommendationModel.query.filter_by(
|
||||||
slug=row[headers["recommendation_slug"]],
|
slug=row[headers["recommendation_slug"]],
|
||||||
).first()
|
).first()
|
||||||
decision = DecisionModel.query.filter_by(
|
decision = model.DecisionModel.query.filter_by(
|
||||||
representative=decision_representative,
|
representative=decision_representative,
|
||||||
recommendation=decision_recommendation,
|
recommendation=decision_recommendation,
|
||||||
).first()
|
).first()
|
||||||
if decision is None:
|
if decision is None:
|
||||||
decision = DecisionModel(
|
decision = model.DecisionModel(
|
||||||
representative = decision_representative,
|
representative = decision_representative,
|
||||||
recommendation = decision_recommendation,
|
recommendation = decision_recommendation,
|
||||||
value = value,
|
value = value,
|
||||||
|
@ -378,13 +321,13 @@ class ImportEntityView(BaseView):
|
||||||
}
|
}
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
for row in reader:
|
for row in reader:
|
||||||
entity_type = TypeModel.query.filter_by(
|
entity_type = model.TypeModel.query.filter_by(
|
||||||
code=row[headers["type_code"]]
|
code=row[headers["type_code"]]
|
||||||
).first()
|
).first()
|
||||||
entity_country = CountryModel.query.filter_by(
|
entity_country = model.CountryModel.query.filter_by(
|
||||||
code=row[headers["country_code"]].upper()
|
code=row[headers["country_code"]].upper()
|
||||||
).first()
|
).first()
|
||||||
entity = EntityModel.query.filter_by(
|
entity = model.EntityModel.query.filter_by(
|
||||||
code=row[headers["code"]]
|
code=row[headers["code"]]
|
||||||
).first()
|
).first()
|
||||||
if row[headers["start"]] != "":
|
if row[headers["start"]] != "":
|
||||||
|
@ -400,7 +343,7 @@ class ImportEntityView(BaseView):
|
||||||
else:
|
else:
|
||||||
picture = None
|
picture = None
|
||||||
if entity is None:
|
if entity is None:
|
||||||
entity = EntityModel(
|
entity = model.EntityModel(
|
||||||
type = entity_type,
|
type = entity_type,
|
||||||
country = entity_country,
|
country = entity_country,
|
||||||
name = row[headers["name"]],
|
name = row[headers["name"]],
|
||||||
|
@ -470,7 +413,7 @@ class ImportMatterView(BaseView):
|
||||||
}
|
}
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
for row in reader:
|
for row in reader:
|
||||||
matter = MatterModel.query.filter_by(
|
matter = model.MatterModel.query.filter_by(
|
||||||
slug=slugify(row[headers["name"]]),
|
slug=slugify(row[headers["name"]]),
|
||||||
).first()
|
).first()
|
||||||
if headers["description"] is not None:
|
if headers["description"] is not None:
|
||||||
|
@ -478,7 +421,7 @@ class ImportMatterView(BaseView):
|
||||||
else:
|
else:
|
||||||
description = None
|
description = None
|
||||||
if matter is None:
|
if matter is None:
|
||||||
matter = DecisionModel(
|
matter = model.DecisionModel(
|
||||||
name = row[headers["name"]],
|
name = row[headers["name"]],
|
||||||
slug = slugify(row[headers["name"]]),
|
slug = slugify(row[headers["name"]]),
|
||||||
description = description,
|
description = description,
|
||||||
|
@ -530,13 +473,13 @@ class ImportMembershipView(BaseView):
|
||||||
}
|
}
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
for row in reader:
|
for row in reader:
|
||||||
representative = RepresentativeModel.query.filter_by(
|
representative = model.RepresentativeModel.query.filter_by(
|
||||||
slug=slugify(row[headers["representative_slug"]]),
|
slug=slugify(row[headers["representative_slug"]]),
|
||||||
).first()
|
).first()
|
||||||
entity = EntityModel.query.filter_by(
|
entity = model.EntityModel.query.filter_by(
|
||||||
code=row[headers["entity_code"]],
|
code=row[headers["entity_code"]],
|
||||||
).first()
|
).first()
|
||||||
role = RoleModel.query.filter_by(
|
role = model.RoleModel.query.filter_by(
|
||||||
code=row[headers["role_code"]],
|
code=row[headers["role_code"]],
|
||||||
).first()
|
).first()
|
||||||
if row[headers["start"]] != "":
|
if row[headers["start"]] != "":
|
||||||
|
@ -547,14 +490,14 @@ class ImportMembershipView(BaseView):
|
||||||
end_date = datetime.strptime(row[headers["end"]], "%Y-%m-%d")
|
end_date = datetime.strptime(row[headers["end"]], "%Y-%m-%d")
|
||||||
else:
|
else:
|
||||||
end_date = None
|
end_date = None
|
||||||
membership = MembershipModel.query.filter_by(
|
membership = model.MembershipModel.query.filter_by(
|
||||||
representative=representative,
|
representative=representative,
|
||||||
entity=entity,
|
entity=entity,
|
||||||
role=role,
|
role=role,
|
||||||
start=start_date,
|
start=start_date,
|
||||||
).first()
|
).first()
|
||||||
if membership is None:
|
if membership is None:
|
||||||
membership = MembershipModel(
|
membership = model.MembershipModel(
|
||||||
representative = representative,
|
representative = representative,
|
||||||
entity = entity,
|
entity = entity,
|
||||||
role = role,
|
role = role,
|
||||||
|
@ -614,10 +557,10 @@ class ImportRecommendationView(BaseView):
|
||||||
}
|
}
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
for row in reader:
|
for row in reader:
|
||||||
matter = MatterModel.query.filter_by(
|
matter = model.MatterModel.query.filter_by(
|
||||||
slug=row[headers["matter_slug"]],
|
slug=row[headers["matter_slug"]],
|
||||||
).first()
|
).first()
|
||||||
entity = EntityModel.query.filter_by(
|
entity = model.EntityModel.query.filter_by(
|
||||||
code=row[headers["entity_code"]],
|
code=row[headers["entity_code"]],
|
||||||
).first()
|
).first()
|
||||||
if row[headers["date"]] != "":
|
if row[headers["date"]] != "":
|
||||||
|
@ -632,13 +575,13 @@ class ImportRecommendationView(BaseView):
|
||||||
weight = int(row[headers["weight"]])
|
weight = int(row[headers["weight"]])
|
||||||
else:
|
else:
|
||||||
weight = 1
|
weight = 1
|
||||||
recommendation = RecommendationModel.query.filter_by(
|
recommendation = model.RecommendationModel.query.filter_by(
|
||||||
matter=matter,
|
matter=matter,
|
||||||
entity=entity,
|
entity=entity,
|
||||||
code=row[headers["code"]],
|
code=row[headers["code"]],
|
||||||
).first()
|
).first()
|
||||||
if recommendation is None:
|
if recommendation is None:
|
||||||
recommendation = RecommendationModel(
|
recommendation = model.RecommendationModel(
|
||||||
matter = matter,
|
matter = matter,
|
||||||
entity = entity,
|
entity = entity,
|
||||||
name = row[headers["name"]],
|
name = row[headers["name"]],
|
||||||
|
@ -676,102 +619,6 @@ class ImportRecommendationView(BaseView):
|
||||||
return self.render("admin/import.html")
|
return self.render("admin/import.html")
|
||||||
|
|
||||||
|
|
||||||
class ImportRepresentativeView(BaseView):
|
|
||||||
@expose("/", methods=["GET", "POST"])
|
|
||||||
def index(self):
|
|
||||||
headers = {
|
|
||||||
"code": None,
|
|
||||||
"name": None,
|
|
||||||
"picture": None,
|
|
||||||
"nationality": None,
|
|
||||||
"sex": None,
|
|
||||||
"birth_date": None,
|
|
||||||
"birth_place": None,
|
|
||||||
"job": None,
|
|
||||||
}
|
|
||||||
reader = default_import(headers)
|
|
||||||
g.what = {
|
|
||||||
"title": "Import representatives",
|
|
||||||
"description": "Importing representatives will add unknown ones and update"
|
|
||||||
" known ones. If a representative is not present in imported file it"
|
|
||||||
" will not be deleted.",
|
|
||||||
"endpoint": "representatives.index",
|
|
||||||
"formats": [
|
|
||||||
"File format accepted is CSV (Comma Separated Values).",
|
|
||||||
"First line chould be column headers.",
|
|
||||||
"Other lines are values.",
|
|
||||||
"One column MUST be 'code' and be the unique identifier of the representative.",
|
|
||||||
"One column MUST be 'name'.",
|
|
||||||
"One column MUST be 'picture'.",
|
|
||||||
"One column MUST be 'nationality' and be an ISO country code.",
|
|
||||||
"One column MUST be 'sex' and be 'F' or 'M'.",
|
|
||||||
"One column MUST be 'birth_date'.",
|
|
||||||
"One column MUST be 'birth_place'.",
|
|
||||||
"One column MUST be 'birth_job'.",
|
|
||||||
],
|
|
||||||
"examples": [
|
|
||||||
"name,iso2,iso3",
|
|
||||||
"France,FR,FRA",
|
|
||||||
"United States of America,US,USA",
|
|
||||||
"Spain,SP,SPA",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
if len(g.errors) == 0 and reader is not None:
|
|
||||||
# Values
|
|
||||||
for row in reader:
|
|
||||||
representative = RepresentativeModel.query.filter_by(
|
|
||||||
code=row[headers["code"]],
|
|
||||||
).first()
|
|
||||||
country = CountryModel.query.filter_by(
|
|
||||||
code=row[headers["nationality"]].upper(),
|
|
||||||
).first()
|
|
||||||
if row[headers["birth_date"]] != "":
|
|
||||||
birth_date = datetime.strptime(row[headers["birth_date"]], "%Y-%m-%d").date()
|
|
||||||
else:
|
|
||||||
birth_date = None
|
|
||||||
if representative is None:
|
|
||||||
representative = RepresentativeModel(
|
|
||||||
code = row[headers["code"]],
|
|
||||||
name = row[headers["name"]],
|
|
||||||
slug = slugify(row[headers["name"]]),
|
|
||||||
picture = row[headers["picture"]],
|
|
||||||
nationality = country,
|
|
||||||
sex = row[headers["sex"]],
|
|
||||||
birth_date = birth_date,
|
|
||||||
birth_place = row[headers["birth_place"]],
|
|
||||||
job = row[headers["job"]],
|
|
||||||
)
|
|
||||||
g.messages.append(f"{row[headers['name']]} added.")
|
|
||||||
representative.save()
|
|
||||||
else:
|
|
||||||
updated = False
|
|
||||||
if representative.picture != row[headers["picture"]]:
|
|
||||||
representative.picture = row[headers["picture"]]
|
|
||||||
updated = True
|
|
||||||
if representative.nationality != country:
|
|
||||||
representative.nationality = country
|
|
||||||
updated = True
|
|
||||||
if representative.sex != row[headers["sex"]]:
|
|
||||||
representative.sex = row[headers["sex"]]
|
|
||||||
updated = True
|
|
||||||
if representative.birth_date != birth_date:
|
|
||||||
print(representative.birth_date)
|
|
||||||
print(birth_date)
|
|
||||||
representative.birth_date = birth_date
|
|
||||||
updated = True
|
|
||||||
if representative.birth_place != row[headers["birth_place"]]:
|
|
||||||
representative.birth_place = row[headers["birth_place"]]
|
|
||||||
updated = True
|
|
||||||
if representative.job != row[headers["job"]]:
|
|
||||||
representative.job = row[headers["job"]]
|
|
||||||
updated = True
|
|
||||||
if updated:
|
|
||||||
g.messages.append(f"{row[headers['name']]} updated.")
|
|
||||||
representative.save()
|
|
||||||
|
|
||||||
return self.render("admin/import.html")
|
|
||||||
|
|
||||||
|
|
||||||
class ImportRoleView(BaseView):
|
class ImportRoleView(BaseView):
|
||||||
@expose("/", methods=["GET", "POST"])
|
@expose("/", methods=["GET", "POST"])
|
||||||
def index(self):
|
def index(self):
|
||||||
|
@ -800,9 +647,9 @@ class ImportRoleView(BaseView):
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
# Values
|
# Values
|
||||||
for row in reader:
|
for row in reader:
|
||||||
role = RoleModel.query.filter_by(code=row[headers["code"]]).first()
|
role = model.RoleModel.query.filter_by(code=row[headers["code"]]).first()
|
||||||
if role is None:
|
if role is None:
|
||||||
role = RoleModel(
|
role = model.RoleModel(
|
||||||
name = row[headers["name"]],
|
name = row[headers["name"]],
|
||||||
slug = slugify(row[headers["name"]]),
|
slug = slugify(row[headers["name"]]),
|
||||||
code = row[headers["code"]],
|
code = row[headers["code"]],
|
||||||
|
@ -856,21 +703,21 @@ class ImportStanceView(BaseView):
|
||||||
# Values
|
# Values
|
||||||
for row in reader:
|
for row in reader:
|
||||||
# Representative
|
# Representative
|
||||||
representative = RepresentativeModel.query.filter_by(
|
representative = model.RepresentativeModel.query.filter_by(
|
||||||
slug=row[headers["slug"]],
|
slug=row[headers["slug"]],
|
||||||
).first()
|
).first()
|
||||||
if representative is None:
|
if representative is None:
|
||||||
representative = RepresentativeModel(
|
representative = model.RepresentativeModel(
|
||||||
name = row[headers["name"]],
|
name = row[headers["name"]],
|
||||||
slug = row[headers["slug"]],
|
slug = row[headers["slug"]],
|
||||||
)
|
)
|
||||||
representative.save()
|
representative.save()
|
||||||
# Matter
|
# Matter
|
||||||
matter = MatterModel.query.filter_by(
|
matter = model.MatterModel.query.filter_by(
|
||||||
slug=slugify(row[headers["matter"]]),
|
slug=slugify(row[headers["matter"]]),
|
||||||
).first()
|
).first()
|
||||||
if matter is None:
|
if matter is None:
|
||||||
matter = MatterModel(
|
matter = model.MatterModel(
|
||||||
name = row[headers["matter"]],
|
name = row[headers["matter"]],
|
||||||
slug = slugify(row[headers["matter"]]),
|
slug = slugify(row[headers["matter"]]),
|
||||||
)
|
)
|
||||||
|
@ -880,7 +727,7 @@ class ImportStanceView(BaseView):
|
||||||
else:
|
else:
|
||||||
stance_date = None
|
stance_date = None
|
||||||
# Stance
|
# Stance
|
||||||
stance = StanceModel.query.filter_by(
|
stance = model.StanceModel.query.filter_by(
|
||||||
representative=representative,
|
representative=representative,
|
||||||
matter=matter,
|
matter=matter,
|
||||||
subject=row[headers["subject"]],
|
subject=row[headers["subject"]],
|
||||||
|
@ -888,7 +735,7 @@ class ImportStanceView(BaseView):
|
||||||
source_url=row[headers["source_url"]],
|
source_url=row[headers["source_url"]],
|
||||||
).first()
|
).first()
|
||||||
if stance is None:
|
if stance is None:
|
||||||
stance = StanceModel(
|
stance = model.StanceModel(
|
||||||
representative = representative,
|
representative = representative,
|
||||||
matter = matter,
|
matter = matter,
|
||||||
subject = row[headers["subject"]],
|
subject = row[headers["subject"]],
|
||||||
|
@ -947,9 +794,9 @@ class ImportTypeView(BaseView):
|
||||||
if len(g.errors) == 0 and reader is not None:
|
if len(g.errors) == 0 and reader is not None:
|
||||||
# Values
|
# Values
|
||||||
for row in reader:
|
for row in reader:
|
||||||
type_ = TypeModel.query.filter_by(code=row[headers["code"]]).first()
|
type_ = model.TypeModel.query.filter_by(code=row[headers["code"]]).first()
|
||||||
if type_ is None:
|
if type_ is None:
|
||||||
type_ = TypeModel(
|
type_ = model.TypeModel(
|
||||||
name = row[headers["name"]],
|
name = row[headers["name"]],
|
||||||
slug = slugify(row[headers["name"]]),
|
slug = slugify(row[headers["name"]]),
|
||||||
code = row[headers["code"]],
|
code = row[headers["code"]],
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from flask import current_app, g, request, redirect, url_for
|
||||||
|
from flask_admin import BaseView, expose
|
||||||
|
from slugify import slugify
|
||||||
|
from sqlalchemy import or_
|
||||||
|
|
||||||
|
from app.form.admin import ImportForm
|
||||||
|
from app.controller.admin.importer import default_import
|
||||||
|
from app.model.entity import EntityModel
|
||||||
|
from app.model.membership import MembershipModel
|
||||||
|
from app.model.representative_origin import RepresentativeOriginModel
|
||||||
|
from app.model.role import RoleModel
|
||||||
|
|
||||||
|
|
||||||
|
class ImportMembershipView(BaseView):
|
||||||
|
@expose("/", methods=["GET", "POST"])
|
||||||
|
def index(self):
|
||||||
|
g.what = {
|
||||||
|
"title": "Import memberships",
|
||||||
|
"description": "Importing memberships will add unknown ones and update"
|
||||||
|
" known ones. If a membership is not present in imported file it"
|
||||||
|
" will not be deleted.",
|
||||||
|
"endpoint": "memberships.index",
|
||||||
|
"formats": [
|
||||||
|
"File format accepted is CSV (Comma Separated Values).",
|
||||||
|
"First line represents column headers.",
|
||||||
|
"Other lines are values:",
|
||||||
|
"One column MUST be 'reference'",
|
||||||
|
"One column MUST be 'representative_reference'",
|
||||||
|
"One column MUST be 'entity_reference'",
|
||||||
|
"One column MUST be 'role_code'",
|
||||||
|
"One column MUST be 'role'",
|
||||||
|
"One column MUST be 'start'",
|
||||||
|
"One column COULD be 'end'",
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"reference,representative_reference,entity_reference,role_code,role,start,end",
|
||||||
|
"12,23,34,MBR,Member,2020-01-01,",
|
||||||
|
"45,67,89,PDT,President,2018-01-01,2019-12-31",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
"reference": None,
|
||||||
|
"representative_reference": None,
|
||||||
|
"entity_reference": None,
|
||||||
|
"role_code": None,
|
||||||
|
"role": None,
|
||||||
|
"start": None,
|
||||||
|
"end": "optional",
|
||||||
|
}
|
||||||
|
reader = default_import(headers)
|
||||||
|
if len(g.errors) == 0 and reader is not None:
|
||||||
|
for row in reader:
|
||||||
|
role = RoleModel.query.filter_by(
|
||||||
|
code=row[headers["role_code"]].upper()
|
||||||
|
).first()
|
||||||
|
if role is None:
|
||||||
|
role = RoleModel(
|
||||||
|
code=row[headers["role_code"]].upper(),
|
||||||
|
name=row[headers["role"]],
|
||||||
|
slug=slugify(row[headers["role"]]),
|
||||||
|
)
|
||||||
|
role.save()
|
||||||
|
|
||||||
|
entity = EntityModel.query.filter_by(
|
||||||
|
reference=row[headers["entity_reference"]].upper()
|
||||||
|
).first()
|
||||||
|
if entity is None:
|
||||||
|
g.messages.append("UNKNOWN entity :"
|
||||||
|
f"{row[headers['entity_reference']].upper()}"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
representative_origin = RepresentativeOriginModel.query.filter_by(
|
||||||
|
reference=row[headers["representative_reference"]].upper(),
|
||||||
|
).first()
|
||||||
|
if representative_origin is None:
|
||||||
|
g.messages.append("UNKNOWN representative :"
|
||||||
|
f"{row[headers['representative_reference']].upper()}"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if row[headers["start"]] != "":
|
||||||
|
start = datetime.strptime(
|
||||||
|
row[headers["start"]], "%Y-%m-%d"
|
||||||
|
).date()
|
||||||
|
else:
|
||||||
|
start = None
|
||||||
|
|
||||||
|
end = None
|
||||||
|
if headers["end"] is not None:
|
||||||
|
if row[headers["end"]] != "":
|
||||||
|
end = datetime.strptime(
|
||||||
|
row[headers["end"]], "%Y-%m-%d"
|
||||||
|
).date()
|
||||||
|
|
||||||
|
membership = MembershipModel.query.filter_by(
|
||||||
|
reference=row[headers["reference"]].upper()
|
||||||
|
).first()
|
||||||
|
if membership is None:
|
||||||
|
membership = MembershipModel(
|
||||||
|
representative_id = representative_origin.representative_id,
|
||||||
|
entity_id = entity.id,
|
||||||
|
reference = row[headers["reference"]].upper(),
|
||||||
|
role_id = role.id,
|
||||||
|
start = start,
|
||||||
|
end = end,
|
||||||
|
active = True if end is None else False,
|
||||||
|
)
|
||||||
|
g.messages.append(
|
||||||
|
f"{role.name} added"
|
||||||
|
f" for {representative_origin.representative.first_name}"
|
||||||
|
f" {representative_origin.representative.last_name}."
|
||||||
|
)
|
||||||
|
membership.save()
|
||||||
|
|
||||||
|
return self.render("admin/import.html")
|
|
@ -0,0 +1,156 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from flask import current_app, g, request, redirect, url_for
|
||||||
|
from flask_admin import BaseView, expose
|
||||||
|
from slugify import slugify
|
||||||
|
from sqlalchemy import or_
|
||||||
|
|
||||||
|
from app.form.admin import ImportForm
|
||||||
|
from app.controller.admin.importer import default_import
|
||||||
|
from app.model.country import CountryModel
|
||||||
|
from app.model.representative import RepresentativeModel
|
||||||
|
from app.model.source import SourceModel
|
||||||
|
from app.model.representative_origin import RepresentativeOriginModel
|
||||||
|
|
||||||
|
|
||||||
|
class ImportRepresentativeView(BaseView):
|
||||||
|
@expose("/", methods=["GET", "POST"])
|
||||||
|
def index(self):
|
||||||
|
g.what = {
|
||||||
|
"title": "Import representatives",
|
||||||
|
"description": "Importing representatives will add unknown ones and update"
|
||||||
|
" known ones. If a representative is not present in imported file it"
|
||||||
|
" will not be deleted.",
|
||||||
|
"endpoint": "representatives.index",
|
||||||
|
"formats": [
|
||||||
|
"File format accepted is CSV (Comma Separated Values).",
|
||||||
|
"First line represents column headers.",
|
||||||
|
"Other lines are values:",
|
||||||
|
"One column MUST be 'source'",
|
||||||
|
"One column MUST be 'reference'",
|
||||||
|
"One column MUST be 'first_name'",
|
||||||
|
"One column MUST be 'last_name'",
|
||||||
|
"One column COULD be 'picture' and be a URI",
|
||||||
|
"One column COULD be 'birth_date'",
|
||||||
|
"One column COULD be 'birth_place'",
|
||||||
|
"One column COULD be 'birth_region'",
|
||||||
|
"One column COULD be 'birth_country'",
|
||||||
|
"One column COULD be 'nationality'",
|
||||||
|
"One column COULD be 'job'",
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"source,reference,first_name,last_name,job",
|
||||||
|
"somewhere,123,Victor,Hugo,Writer",
|
||||||
|
"somewhere,456,Antonio,Vivaldi,Musician",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
"source": None,
|
||||||
|
"reference": None,
|
||||||
|
"first_name": None,
|
||||||
|
"last_name": None,
|
||||||
|
"picture": "optional",
|
||||||
|
"birth_date": "optional",
|
||||||
|
"birth_place": "optional",
|
||||||
|
"birth_region": "optional",
|
||||||
|
"birth_country": "optional",
|
||||||
|
"nationality": "optional",
|
||||||
|
"job": "optional",
|
||||||
|
}
|
||||||
|
reader = default_import(headers)
|
||||||
|
if len(g.errors) == 0 and reader is not None:
|
||||||
|
for row in reader:
|
||||||
|
if row[headers["nationality"]] !="":
|
||||||
|
nationality = CountryModel.query.filter(or_(
|
||||||
|
CountryModel.slug == slugify(row[headers["nationality"]]),
|
||||||
|
CountryModel.alpha_2 == row[headers["nationality"]].upper(),
|
||||||
|
)).first()
|
||||||
|
if nationality is None:
|
||||||
|
if len(row[headers["nationality"]])==2:
|
||||||
|
nationality = CountryModel(
|
||||||
|
name=row[headers["nationality"]],
|
||||||
|
slug=slugify(row[headers["nationality"]]),
|
||||||
|
alpha_2=row[headers["nationality"]].upper(),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
nationality = CountryModel(
|
||||||
|
name=row[headers["nationality"]],
|
||||||
|
slug=slugify(row[headers["nationality"]]),
|
||||||
|
)
|
||||||
|
nationality.save()
|
||||||
|
|
||||||
|
if row[headers["birth_country"]] !="":
|
||||||
|
birth_country = CountryModel.query.filter(or_(
|
||||||
|
CountryModel.slug == slugify(row[headers["birth_country"]]),
|
||||||
|
CountryModel.alpha_2 == row[headers["birth_country"]].upper(),
|
||||||
|
)).first()
|
||||||
|
if birth_country is None:
|
||||||
|
if len(row[headers["birth_country"]])==2:
|
||||||
|
birth_country = CountryModel(
|
||||||
|
name=row[headers["birth_country"]],
|
||||||
|
slug=slugify(row[headers["birth_country"]]),
|
||||||
|
alpha_2=row[headers["birth_country"]].upper(),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
birth_country = CountryModel(
|
||||||
|
name=row[headers["birth_country"]],
|
||||||
|
slug=slugify(row[headers["birth_country"]]),
|
||||||
|
)
|
||||||
|
birth_country.save()
|
||||||
|
|
||||||
|
if row[headers["birth_date"]] != "":
|
||||||
|
birth_date = datetime.strptime(
|
||||||
|
row[headers["birth_date"]], "%Y-%m-%d"
|
||||||
|
).date()
|
||||||
|
else:
|
||||||
|
birth_date = None
|
||||||
|
|
||||||
|
source = SourceModel.query.filter_by(
|
||||||
|
slug=slugify(row[headers["source"]]),
|
||||||
|
).first()
|
||||||
|
if source is None:
|
||||||
|
source = SourceModel(
|
||||||
|
name = row[headers["source"]],
|
||||||
|
slug = slugify(row[headers["source"]]),
|
||||||
|
)
|
||||||
|
source.save()
|
||||||
|
|
||||||
|
representative = RepresentativeModel.query.filter_by(
|
||||||
|
last_name=row[headers["last_name"]],
|
||||||
|
).filter_by(
|
||||||
|
first_name=row[headers["first_name"]],
|
||||||
|
).first()
|
||||||
|
if representative is None:
|
||||||
|
representative = RepresentativeModel(
|
||||||
|
first_name = row[headers["first_name"]],
|
||||||
|
last_name = row[headers["last_name"]],
|
||||||
|
birth_date = birth_date,
|
||||||
|
birth_place = row[headers["birth_place"]],
|
||||||
|
birth_region = row[headers["birth_region"]],
|
||||||
|
birth_country = birth_country,
|
||||||
|
job = row[headers["job"]],
|
||||||
|
nationality = nationality,
|
||||||
|
picture = row[headers["picture"]],
|
||||||
|
)
|
||||||
|
g.messages.append(
|
||||||
|
f"{row[headers['first_name']]} {row[headers['last_name']]}"
|
||||||
|
" added."
|
||||||
|
)
|
||||||
|
representative.save()
|
||||||
|
|
||||||
|
representative_origin = RepresentativeOriginModel.query.filter_by(
|
||||||
|
source_id=source.id,
|
||||||
|
).filter_by(
|
||||||
|
reference=row[headers["reference"]].upper(),
|
||||||
|
).first()
|
||||||
|
if representative_origin is None:
|
||||||
|
representative_origin = RepresentativeOriginModel(
|
||||||
|
source_id = source.id,
|
||||||
|
representative_id = representative.id,
|
||||||
|
reference = row[headers["reference"]].upper(),
|
||||||
|
)
|
||||||
|
representative_origin.save()
|
||||||
|
|
||||||
|
return self.render("admin/import.html")
|
|
@ -1,45 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
from flask import request, current_app
|
|
||||||
from flask_restful import Resource
|
|
||||||
from sqlalchemy import or_
|
|
||||||
|
|
||||||
from app.model.country import CountryModel
|
|
||||||
|
|
||||||
|
|
||||||
class CountriesApi(Resource):
|
|
||||||
def get(self):
|
|
||||||
page = int(request.args.get("page", 1))
|
|
||||||
query = CountryModel.query
|
|
||||||
if request.args.get("name", "") != "":
|
|
||||||
query = query.filter(
|
|
||||||
CountryModel
|
|
||||||
.name
|
|
||||||
.like('%%%s%%' % request.args.get("name", ""))
|
|
||||||
)
|
|
||||||
if request.args.get("iso2", "") != "":
|
|
||||||
query = query.filter_by(iso2=request.args.get("iso2", "").upper())
|
|
||||||
if request.args.get("iso3", "") != "":
|
|
||||||
query = query.filter_by(iso3=request.args.get("iso3", "").upper())
|
|
||||||
if request.args.get("m49", "") != "":
|
|
||||||
query = query.filter_by(m49=request.args.get("m49", "").upper())
|
|
||||||
query = query.order_by(CountryModel.name)
|
|
||||||
return [
|
|
||||||
country.serialize()
|
|
||||||
for country
|
|
||||||
in query
|
|
||||||
.paginate(page, current_app.config['API_PER_PAGE'], error_out=False)
|
|
||||||
.items
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CountryApi(Resource):
|
|
||||||
def get(self, country_id):
|
|
||||||
country = CountryModel.query.filter(or_(
|
|
||||||
CountryModel.iso2==country_id,
|
|
||||||
CountryModel.iso3==country_id,
|
|
||||||
CountryModel.m49==country_id,
|
|
||||||
)).first()
|
|
||||||
if country is None:
|
|
||||||
return None, 404
|
|
||||||
return country.serialize()
|
|
|
@ -10,20 +10,61 @@ from app.model.representative import RepresentativeModel
|
||||||
class RepresentativesApi(Resource):
|
class RepresentativesApi(Resource):
|
||||||
def get(self):
|
def get(self):
|
||||||
page = int(request.args.get("page", 1))
|
page = int(request.args.get("page", 1))
|
||||||
|
print(page)
|
||||||
query = RepresentativeModel.query
|
query = RepresentativeModel.query
|
||||||
if request.args.get("name", "") != "":
|
if request.args.get("name", "") != "":
|
||||||
query = query.filter(
|
query = query.filter(or_(
|
||||||
RepresentativeModel
|
RepresentativeModel.last_name.like(
|
||||||
.name
|
f"%{request.args.get('name')}%"
|
||||||
.like('%%%s%%' % request.args.get("name", ""))
|
),
|
||||||
)
|
RepresentativeModel.first_name.like(
|
||||||
query = query.order_by(RepresentativeModel.name)
|
f"%{request.args.get('name')}%"
|
||||||
|
),
|
||||||
|
))
|
||||||
|
query = query.order_by(RepresentativeModel.last_name)
|
||||||
return [
|
return [
|
||||||
representative.serialize()
|
{
|
||||||
|
"first_name": representative.first_name,
|
||||||
|
"last_name": representative.last_name,
|
||||||
|
"full_name": representative.full_name,
|
||||||
|
"picture": representative.picture,
|
||||||
|
"active": True,
|
||||||
|
"memberships": [
|
||||||
|
{
|
||||||
|
"reference": membership.reference,
|
||||||
|
"source": membership.entity.source,
|
||||||
|
"start_date": membership.start.strftime("%Y-%m-%d"),
|
||||||
|
"end_date": membership.end.strftime("%Y-%m-%d") if membership.end is not None else None,
|
||||||
|
"entity": {
|
||||||
|
"reference": membership.entity.reference,
|
||||||
|
"type": {
|
||||||
|
"code": membership.entity.type.code,
|
||||||
|
"name": membership.entity.type.name,
|
||||||
|
},
|
||||||
|
"name": membership.entity.name,
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"code": membership.role.code,
|
||||||
|
"name": membership.role.name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for membership
|
||||||
|
in representative.memberships
|
||||||
|
|
||||||
|
],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"reference": reference.reference,
|
||||||
|
"source": reference.source.name,
|
||||||
|
}
|
||||||
|
for reference
|
||||||
|
in representative.references
|
||||||
|
],
|
||||||
|
}
|
||||||
for representative
|
for representative
|
||||||
in query
|
in query.paginate(
|
||||||
.paginate(page, current_app.config['API_PER_PAGE'], error_out=False)
|
page, current_app.config["API_PER_PAGE"], error_out=False
|
||||||
.items
|
).items
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,4 +73,5 @@ class RepresentativeApi(Resource):
|
||||||
representative = RepresentativeModel.query.get(representative_id)
|
representative = RepresentativeModel.query.get(representative_id)
|
||||||
if representative is None:
|
if representative is None:
|
||||||
return None, 404
|
return None, 404
|
||||||
|
print(representative.serialize())
|
||||||
return representative.serialize()
|
return representative.serialize()
|
||||||
|
|
|
@ -5,41 +5,16 @@ import random
|
||||||
|
|
||||||
from flask import g, render_template
|
from flask import g, render_template
|
||||||
|
|
||||||
|
from app import model
|
||||||
from app.controller.controller import Controller
|
from app.controller.controller import Controller
|
||||||
from app.model.decision import DecisionModel
|
|
||||||
from app.model.matter import MatterModel
|
|
||||||
from app.model.recommendation import RecommendationModel
|
|
||||||
from app.model.representative import RepresentativeModel
|
|
||||||
from app.model.stance import StanceModel
|
|
||||||
from sqlalchemy import desc
|
from sqlalchemy import desc
|
||||||
from sqlalchemy.sql.expression import func
|
from sqlalchemy.sql.expression import func
|
||||||
|
|
||||||
|
|
||||||
class Core(Controller):
|
class Core(Controller):
|
||||||
def home(self):
|
def home(self):
|
||||||
random.seed(int(datetime.today().timestamp()/100))
|
|
||||||
try:
|
|
||||||
g.motd = random.choice(MatterModel.query.filter_by(
|
|
||||||
active=True
|
|
||||||
).all())
|
|
||||||
except:
|
|
||||||
g.motd = None
|
|
||||||
g.rotd = random.choice(RepresentativeModel.query.filter_by(
|
|
||||||
active=True
|
|
||||||
).all())
|
|
||||||
g.last_decisions = DecisionModel.query.join(DecisionModel.recommendation).order_by(RecommendationModel.date.desc()).limit(10).all()
|
|
||||||
g.last_stances = StanceModel.query.order_by(StanceModel.date.desc()).limit(10).all()
|
|
||||||
return render_template("core/home.html")
|
return render_template("core/home.html")
|
||||||
|
|
||||||
def representative(self, representative_id=None):
|
|
||||||
if representative_id is None:
|
|
||||||
representative_id = random.choice(RepresentativeModel.query.filter_by(
|
|
||||||
active=True
|
|
||||||
).all()).id
|
|
||||||
g.representative = RepresentativeModel.query.get(representative_id)
|
|
||||||
g.title = g.representative.name
|
|
||||||
return render_template("core/representative.html")
|
|
||||||
|
|
||||||
def about(self):
|
def about(self):
|
||||||
return render_template("core/about.html")
|
return render_template("core/about.html")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import random
|
||||||
|
|
||||||
|
from flask import g, redirect, render_template, url_for
|
||||||
|
|
||||||
|
from app import model
|
||||||
|
from app.controller.controller import Controller
|
||||||
|
|
||||||
|
|
||||||
|
class Representative(Controller):
|
||||||
|
def view(self, representative_id=None):
|
||||||
|
if representative_id is None:
|
||||||
|
g.representative = random.choice(
|
||||||
|
model.RepresentativeModel.query.filter_by(active=True).all()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
g.representative = model.RepresentativeModel.query.get(representative_id)
|
||||||
|
if g.representative is None:
|
||||||
|
return redirect(url_for("core.home"))
|
||||||
|
g.title = g.representative.name
|
||||||
|
return render_template("representative/view.html")
|
|
@ -3,16 +3,12 @@
|
||||||
This module imports models to allow alembic and flask to find them.
|
This module imports models to allow alembic and flask to find them.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from app.model.user import UserModel
|
||||||
from app.model.country import CountryModel
|
from app.model.country import CountryModel
|
||||||
from app.model.representative import RepresentativeModel
|
|
||||||
from app.model.address import AddressModel
|
|
||||||
from app.model.contact import ContactModel
|
|
||||||
from app.model.type import TypeModel
|
from app.model.type import TypeModel
|
||||||
from app.model.entity import EntityModel
|
from app.model.entity import EntityModel
|
||||||
|
from app.model.representative import RepresentativeModel
|
||||||
from app.model.role import RoleModel
|
from app.model.role import RoleModel
|
||||||
|
from app.model.source import SourceModel
|
||||||
|
from app.model.representative_origin import RepresentativeOriginModel
|
||||||
from app.model.membership import MembershipModel
|
from app.model.membership import MembershipModel
|
||||||
|
|
||||||
from app.model.matter import MatterModel
|
|
||||||
from app.model.recommendation import RecommendationModel
|
|
||||||
from app.model.decision import DecisionModel
|
|
||||||
from app.model.stance import StanceModel
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
from app import admin, db
|
|
||||||
from app.model.model import Model, View
|
|
||||||
|
|
||||||
|
|
||||||
class AddressModel(db.Model, Model):
|
|
||||||
__tablename__ = "address"
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
name = db.Column(db.String(2000))
|
|
||||||
slug = db.Column(db.String(2000))
|
|
||||||
country_id = db.Column(db.Integer, db.ForeignKey("country.id"))
|
|
||||||
country = db.relationship("CountryModel")
|
|
||||||
number = db.Column(db.String(2000))
|
|
||||||
street = db.Column(db.String(2000))
|
|
||||||
miscellaneous = db.Column(db.String(2000))
|
|
||||||
city = db.Column(db.String(2000))
|
|
||||||
zipcode = db.Column(db.String(2000))
|
|
||||||
building = db.Column(db.String(2000))
|
|
||||||
floor = db.Column(db.String(2000))
|
|
||||||
stair = db.Column(db.String(2000))
|
|
||||||
office = db.Column(db.String(2000))
|
|
||||||
latitude = db.Column(db.String(2000))
|
|
||||||
longitude = db.Column(db.String(2000))
|
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
|
||||||
column_default_sort = [("name", False), ("country.name", True)]
|
|
||||||
column_filters = ["name", "country.name"]
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(AddressModel, db.session, name="Address", category="CRUD"))
|
|
|
@ -1,34 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
from app import admin, db
|
|
||||||
from app.model.model import Model, View
|
|
||||||
|
|
||||||
|
|
||||||
class ContactModel(db.Model, Model):
|
|
||||||
__tablename__ = "contact"
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
representative_id = db.Column(db.Integer, db.ForeignKey("representative.id"))
|
|
||||||
representative = db.relationship(
|
|
||||||
"RepresentativeModel", backref=db.backref("contacts", lazy="dynamic")
|
|
||||||
)
|
|
||||||
address_id = db.Column(db.Integer, db.ForeignKey("address.id"))
|
|
||||||
address = db.relationship(
|
|
||||||
"AddressModel", backref=db.backref("contacts", lazy="dynamic")
|
|
||||||
)
|
|
||||||
name = db.Column(db.String(2000))
|
|
||||||
slug = db.Column(db.String(2000))
|
|
||||||
value = db.Column(db.String(2000))
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
|
||||||
column_default_sort = "name"
|
|
||||||
column_filters = ["representative.name", "name"]
|
|
||||||
|
|
||||||
def on_model_change(self, form, model, is_created):
|
|
||||||
model.slug = slugify(model.name)
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(ContactModel, db.session, name="Contact", category="CRUD"))
|
|
|
@ -7,27 +7,14 @@ from app.model.model import Model, View
|
||||||
class CountryModel(db.Model, Model):
|
class CountryModel(db.Model, Model):
|
||||||
__tablename__ = "country"
|
__tablename__ = "country"
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(2000))
|
name = db.Column(db.String(200))
|
||||||
slug = db.Column(db.String(2000))
|
slug = db.Column(db.String(200))
|
||||||
code = db.Column(db.String(2000))
|
official_state_name = db.Column(db.String(200))
|
||||||
|
alpha_2 = db.Column(db.String(2))
|
||||||
@property
|
alpha_3 = db.Column(db.String(3))
|
||||||
def flag(self):
|
|
||||||
"""
|
|
||||||
HTML unicode sequence for display country flag.
|
|
||||||
"""
|
|
||||||
return "".join([f"&#{hex(127397+ord(l))[1:]};" for l in self.code])
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
admin.add_view(View(CountryModel, db.session, name="Country", category="CRUD"))
|
||||||
column_default_sort = "name"
|
|
||||||
column_filters = ["name", "code"]
|
|
||||||
|
|
||||||
def on_model_change(self, form, model, is_created):
|
|
||||||
model.slug = slugify(model.name)
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(CountryModel, db.session, name="Country", category="CRUD"))
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
from app import admin, db
|
|
||||||
from app.model.model import Model, View
|
|
||||||
|
|
||||||
|
|
||||||
class DecisionModel(db.Model, Model):
|
|
||||||
__tablename__ = "decision"
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
representative_id = db.Column(db.Integer, db.ForeignKey("representative.id"))
|
|
||||||
representative = db.relationship(
|
|
||||||
"RepresentativeModel", backref=db.backref("decisions", lazy="dynamic")
|
|
||||||
)
|
|
||||||
recommendation_id = db.Column(db.Integer, db.ForeignKey("recommendation.id"))
|
|
||||||
recommendation = db.relationship(
|
|
||||||
"RecommendationModel", backref=db.backref("decisions", lazy="dynamic")
|
|
||||||
)
|
|
||||||
value = db.Column(db.String(2000))
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self.value
|
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
|
||||||
column_default_sort = "value"
|
|
||||||
column_filters = ["representative.name", "recommendation.name"]
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(DecisionModel, db.session, name="Decision", category="CRUD"))
|
|
|
@ -1,7 +1,5 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
from slugify import slugify
|
|
||||||
|
|
||||||
from app import admin, db
|
from app import admin, db
|
||||||
from app.model.model import Model, View
|
from app.model.model import Model, View
|
||||||
|
|
||||||
|
@ -9,18 +7,19 @@ from app.model.model import Model, View
|
||||||
class EntityModel(db.Model, Model):
|
class EntityModel(db.Model, Model):
|
||||||
__tablename__ = "entity"
|
__tablename__ = "entity"
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(2000))
|
parent_id = db.Column(db.Integer, db.ForeignKey("entity.id"))
|
||||||
slug = db.Column(db.String(2000))
|
children = db.relationship(
|
||||||
code = db.Column(db.String(2000))
|
"EntityModel", backref=db.backref("parent", remote_side=id)
|
||||||
picture = db.Column(db.String(2000))
|
)
|
||||||
|
name = db.Column(db.String(500))
|
||||||
|
slug = db.Column(db.String(500))
|
||||||
|
reference = db.Column(db.String(200))
|
||||||
|
source = db.Column(db.String(200))
|
||||||
type_id = db.Column(db.Integer, db.ForeignKey("type.id"))
|
type_id = db.Column(db.Integer, db.ForeignKey("type.id"))
|
||||||
type = db.relationship("TypeModel")
|
type = db.relationship("TypeModel")
|
||||||
start = db.Column(db.DateTime)
|
start = db.Column(db.Date)
|
||||||
end = db.Column(db.DateTime)
|
end = db.Column(db.Date)
|
||||||
country_id = db.Column(db.Integer, db.ForeignKey("country.id"))
|
active = db.Column(db.Boolean)
|
||||||
country = db.relationship("CountryModel")
|
|
||||||
parent_id = db.Column(db.Integer, db.ForeignKey("entity.id"))
|
|
||||||
parent = db.relationship("EntityModel")
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -28,10 +27,6 @@ class EntityModel(db.Model, Model):
|
||||||
|
|
||||||
class AdminView(View):
|
class AdminView(View):
|
||||||
column_default_sort = "name"
|
column_default_sort = "name"
|
||||||
column_filters = ["name", "code", "type.name", "country.name"]
|
column_filters = ["name", "reference", "parent.name", "start", "end", "active"]
|
||||||
|
|
||||||
def on_model_change(self, form, model, is_created):
|
|
||||||
model.slug = slugify(model.name)
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(EntityModel, db.session, name="Entity", category="CRUD"))
|
admin.add_view(AdminView(EntityModel, db.session, name="Entity", category="CRUD"))
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
from slugify import slugify
|
|
||||||
|
|
||||||
from app import admin, db
|
|
||||||
from app.model.model import Model, View
|
|
||||||
|
|
||||||
|
|
||||||
class MatterModel(db.Model, Model):
|
|
||||||
__tablename__ = "matter"
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
name = db.Column(db.String(2000))
|
|
||||||
slug = db.Column(db.String(2000), unique=True)
|
|
||||||
description = db.Column(db.Text)
|
|
||||||
active = db.Column(db.Boolean, default=False)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
|
||||||
column_default_sort = "name"
|
|
||||||
column_filters = ["name"]
|
|
||||||
form_columns = ["name", "description", "active"]
|
|
||||||
|
|
||||||
def on_model_change(self, form, model, is_created):
|
|
||||||
model.slug = slugify(model.name)
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(MatterModel, db.session, name="Matter", category="CRUD"))
|
|
|
@ -11,28 +11,25 @@ class MembershipModel(db.Model, Model):
|
||||||
representative = db.relationship(
|
representative = db.relationship(
|
||||||
"RepresentativeModel", backref=db.backref("memberships", lazy="dynamic")
|
"RepresentativeModel", backref=db.backref("memberships", lazy="dynamic")
|
||||||
)
|
)
|
||||||
role_id = db.Column(db.Integer, db.ForeignKey("role.id"))
|
|
||||||
role = db.relationship(
|
|
||||||
"RoleModel", backref=db.backref("memberships", lazy="dynamic")
|
|
||||||
)
|
|
||||||
start = db.Column(db.DateTime)
|
|
||||||
end = db.Column(db.DateTime)
|
|
||||||
entity_id = db.Column(db.Integer, db.ForeignKey("entity.id"))
|
entity_id = db.Column(db.Integer, db.ForeignKey("entity.id"))
|
||||||
entity = db.relationship(
|
entity = db.relationship(
|
||||||
"EntityModel", backref=db.backref("memberships", lazy="dynamic")
|
"EntityModel", backref=db.backref("memberships", lazy="dynamic")
|
||||||
)
|
)
|
||||||
|
reference = db.Column(db.String(200))
|
||||||
@property
|
role_id = db.Column(db.Integer, db.ForeignKey("role.id"))
|
||||||
def timestamp(self):
|
role = db.relationship("RoleModel")
|
||||||
if self.end is None:
|
start = db.Column(db.Date)
|
||||||
return 9999999999 + self.start.timestamp()
|
end = db.Column(db.Date)
|
||||||
else:
|
active = db.Column(db.Boolean)
|
||||||
return self.end.timestamp()
|
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
class AdminView(View):
|
||||||
column_default_sort = [("representative.name", False), ("entity.name", False)]
|
column_filters = [
|
||||||
column_filters = ["representative.name", "entity.name", "role.name"]
|
"entity.name", "entity.type.name", "representative.full_name", "role.name",
|
||||||
|
"start", "end", "active",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(MembershipModel, db.session, name="Membership", category="CRUD"))
|
admin.add_view(
|
||||||
|
AdminView(MembershipModel, db.session, name="Membership", category="CRUD")
|
||||||
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime, date
|
||||||
|
|
||||||
from flask import redirect, request, url_for
|
from flask import redirect, request, url_for
|
||||||
from flask_admin.contrib.sqla import ModelView
|
from flask_admin.contrib.sqla import ModelView
|
||||||
|
@ -11,14 +11,14 @@ from app import db
|
||||||
|
|
||||||
class View(ModelView):
|
class View(ModelView):
|
||||||
def is_accessible(self):
|
def is_accessible(self):
|
||||||
# TODO: develop mode
|
# TODO: develop mode, refer to current_app.config.debug
|
||||||
return True
|
return True
|
||||||
if not current_user.is_authenticated:
|
if not current_user.is_authenticated:
|
||||||
return False
|
return False
|
||||||
return current_user.is_authenticated and current_user.admin
|
return current_user.is_authenticated and current_user.admin
|
||||||
|
|
||||||
def inaccessible_callback(self, name, **kwargs):
|
def inaccessible_callback(self, name, **kwargs):
|
||||||
# TODO: develop mode
|
# TODO: develop mode, refer to current_app.config.debug
|
||||||
return redirect(url_for("core.login"))
|
return redirect(url_for("core.login"))
|
||||||
return redirect(url_for("admin.login", next=request.url))
|
return redirect(url_for("admin.login", next=request.url))
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ class Model:
|
||||||
result_dict = {}
|
result_dict = {}
|
||||||
for key in self.__table__.columns.keys():
|
for key in self.__table__.columns.keys():
|
||||||
if not key.startswith("_"):
|
if not key.startswith("_"):
|
||||||
if isinstance(getattr(self, key), datetime):
|
if isinstance(getattr(self, key), (datetime, date)):
|
||||||
result_dict[key] = getattr(self, key).strftime("%Y-%m-%d")
|
result_dict[key] = getattr(self, key).strftime("%Y-%m-%d")
|
||||||
else:
|
else:
|
||||||
result_dict[key] = getattr(self, key)
|
result_dict[key] = getattr(self, key)
|
||||||
return result_dict
|
return result_dict
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
from slugify import slugify
|
|
||||||
|
|
||||||
from app import admin, db
|
|
||||||
from app.model.model import Model, View
|
|
||||||
|
|
||||||
|
|
||||||
class RecommendationModel(db.Model, Model):
|
|
||||||
__tablename__ = "recommendation"
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
matter_id = db.Column(db.Integer, db.ForeignKey("matter.id"))
|
|
||||||
matter = db.relationship(
|
|
||||||
"MatterModel", backref=db.backref("recommendations", lazy="dynamic")
|
|
||||||
)
|
|
||||||
entity_id = db.Column(db.Integer, db.ForeignKey("entity.id"))
|
|
||||||
entity = db.relationship(
|
|
||||||
"EntityModel", backref=db.backref("recommendations", lazy="dynamic")
|
|
||||||
)
|
|
||||||
name = db.Column(db.String(2000))
|
|
||||||
slug = db.Column(db.String(2000), unique=True)
|
|
||||||
code = db.Column(db.String(2000))
|
|
||||||
date = db.Column(db.Date)
|
|
||||||
description = db.Column(db.Text)
|
|
||||||
value = db.Column(db.String(2000))
|
|
||||||
weight = db.Column(db.Integer, default=1)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"{self.name} - {self.value} ({self.weight})"
|
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
|
||||||
column_default_sort = "name"
|
|
||||||
column_filters = ["name", "matter.name"]
|
|
||||||
form_columns = ["matter", "entity", "name", "code", "date", "description", "value", "weight"]
|
|
||||||
|
|
||||||
def on_model_change(self, form, model, is_created):
|
|
||||||
model.slug = slugify(model.name)
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(
|
|
||||||
AdminView(RecommendationModel, db.session, name="Recommendation", category="CRUD")
|
|
||||||
)
|
|
|
@ -2,75 +2,42 @@
|
||||||
|
|
||||||
from app import admin, db
|
from app import admin, db
|
||||||
from app.model.model import Model, View
|
from app.model.model import Model, View
|
||||||
from app.model.country import CountryModel
|
|
||||||
|
from sqlalchemy.ext.hybrid import hybrid_property
|
||||||
|
|
||||||
|
|
||||||
class RepresentativeModel(db.Model, Model):
|
class RepresentativeModel(db.Model, Model):
|
||||||
__tablename__ = "representative"
|
__tablename__ = "representative"
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
code = db.Column(db.String(2000), unique=True)
|
first_name = db.Column(db.String(200))
|
||||||
name = db.Column(db.String(2000))
|
last_name = db.Column(db.String(200))
|
||||||
slug = db.Column(db.String(2000))
|
birth_date = db.Column(db.Date)
|
||||||
active = db.Column(db.Boolean, default=False)
|
birth_place = db.Column(db.String(200))
|
||||||
picture = db.Column(db.String(2000))
|
birth_region = db.Column(db.String(200))
|
||||||
|
birth_country_id = db.Column(db.Integer, db.ForeignKey("country.id"))
|
||||||
|
birth_country = db.relationship(
|
||||||
|
"CountryModel", foreign_keys="RepresentativeModel.birth_country_id"
|
||||||
|
)
|
||||||
|
job = db.Column(db.String(200))
|
||||||
nationality_id = db.Column(db.Integer, db.ForeignKey("country.id"))
|
nationality_id = db.Column(db.Integer, db.ForeignKey("country.id"))
|
||||||
nationality = db.relationship(
|
nationality = db.relationship(
|
||||||
"CountryModel", foreign_keys=[nationality_id], backref=db.backref("representatives", lazy="dynamic")
|
"CountryModel", foreign_keys="RepresentativeModel.nationality_id"
|
||||||
)
|
)
|
||||||
sex = db.Column(db.String(1))
|
picture = db.Column(db.String(200))
|
||||||
birth_date = db.Column(db.Date)
|
|
||||||
birth_place = db.Column(db.String(2000))
|
|
||||||
job = db.Column(db.String(2000))
|
|
||||||
|
|
||||||
@property
|
@hybrid_property
|
||||||
def parpol(self):
|
def full_name(self):
|
||||||
"""
|
return self.first_name + " " + self.last_name
|
||||||
A representative is maybe part of a political party.
|
|
||||||
"""
|
|
||||||
# Active one first
|
|
||||||
for membership in [membership for membership in self.memberships if membership.end is None]:
|
|
||||||
if membership.entity.type.code == "PARPOL":
|
|
||||||
return membership.entity.name
|
|
||||||
# Else old one
|
|
||||||
for membership in sorted(self.memberships, key=lambda x: x.start, reverse=True):
|
|
||||||
if membership.entity.type.code == "PARPOL":
|
|
||||||
return membership.entity.name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_female(self):
|
|
||||||
return self.sex == "F"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_active(self):
|
|
||||||
"""
|
|
||||||
A representative is active if she has at least one membership not ended.
|
|
||||||
"""
|
|
||||||
for membership in self.memberships:
|
|
||||||
if membership.end is None:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def score(self):
|
|
||||||
total = 0
|
|
||||||
for decision in self.decisions:
|
|
||||||
if decision.value == decision.recommendation.value:
|
|
||||||
total += decision.recommendation.weight
|
|
||||||
else:
|
|
||||||
total -= decision.recommendation.weight
|
|
||||||
return total
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name
|
return f"{self.first_name.capitalize()} {self.last_name.upper()}"
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
class AdminView(View):
|
||||||
column_default_sort = "name"
|
column_default_sort = "last_name"
|
||||||
column_exclude_list = ["picture"]
|
column_exclude_list = [
|
||||||
column_filters = ["name", "nationality.name"]
|
"birth_region", "birth_country", "picture",
|
||||||
|
]
|
||||||
def on_model_change(self, form, model, is_created):
|
column_filters = ["last_name", "first_name", "nationality.name", ]
|
||||||
model.slug = slugify(model.name)
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(RepresentativeModel, db.session, name="Representative", category="CRUD"))
|
admin.add_view(AdminView(RepresentativeModel, db.session, name="Representative", category="CRUD"))
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from app import admin, db
|
||||||
|
from app.model.model import Model, View
|
||||||
|
|
||||||
|
|
||||||
|
class RepresentativeOriginModel(db.Model, Model):
|
||||||
|
__tablename__ = "representative_origin"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
representative_id = db.Column(db.Integer, db.ForeignKey("representative.id"))
|
||||||
|
representative = db.relationship(
|
||||||
|
"RepresentativeModel", backref=db.backref("references", lazy="dynamic")
|
||||||
|
)
|
||||||
|
source_id = db.Column(db.Integer, db.ForeignKey("source.id"))
|
||||||
|
source = db.relationship("SourceModel")
|
||||||
|
reference = db.Column(db.String(200))
|
||||||
|
|
||||||
|
|
||||||
|
admin.add_view(View(
|
||||||
|
RepresentativeOriginModel, db.session, name="RepresentativeOrigin", category="CRUD"
|
||||||
|
))
|
|
@ -7,20 +7,12 @@ from app.model.model import Model, View
|
||||||
class RoleModel(db.Model, Model):
|
class RoleModel(db.Model, Model):
|
||||||
__tablename__ = "role"
|
__tablename__ = "role"
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(2000))
|
code = db.Column(db.String(200))
|
||||||
slug = db.Column(db.String(2000))
|
name = db.Column(db.String(200))
|
||||||
code = db.Column(db.String(2000))
|
slug = db.Column(db.String(200))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
admin.add_view(View(RoleModel, db.session, name="Role", category="CRUD"))
|
||||||
column_default_sort = "name"
|
|
||||||
column_filters = ["name", "code"]
|
|
||||||
|
|
||||||
def on_model_change(self, form, model, is_created):
|
|
||||||
model.slug = slugify(model.name)
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(RoleModel, db.session, name="Role", category="CRUD"))
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from app import admin, db
|
||||||
|
from app.model.model import Model, View
|
||||||
|
|
||||||
|
|
||||||
|
class SourceModel(db.Model, Model):
|
||||||
|
__tablename__ = "source"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(200))
|
||||||
|
slug = db.Column(db.String(200))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
admin.add_view(View(SourceModel, db.session, name="Source", category="CRUD"))
|
|
@ -1,44 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
from app import admin, db
|
|
||||||
from app.model.model import Model, View
|
|
||||||
from app.model.matter import MatterModel
|
|
||||||
from app.model.representative import RepresentativeModel
|
|
||||||
|
|
||||||
|
|
||||||
class StanceModel(db.Model, Model):
|
|
||||||
__tablename__ = "stance"
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
representative_id = db.Column(db.Integer, db.ForeignKey("representative.id"))
|
|
||||||
representative = db.relationship(
|
|
||||||
"RepresentativeModel", backref=db.backref("stances", lazy="dynamic")
|
|
||||||
)
|
|
||||||
matter_id = db.Column(db.Integer, db.ForeignKey("matter.id"), nullable=True)
|
|
||||||
matter = db.relationship(
|
|
||||||
"MatterModel", backref=db.backref("stances", lazy="dynamic")
|
|
||||||
)
|
|
||||||
date = db.Column(db.Date)
|
|
||||||
subject = db.Column(db.String(2000))
|
|
||||||
extract = db.Column(db.Text)
|
|
||||||
source_url = db.Column(db.String(2000))
|
|
||||||
active = db.Column(db.Boolean, default=False)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self.representative.name + " : " + self.extract[:50]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def extract_html(self):
|
|
||||||
return "<p>" + self.extract.replace("\n", "</p><p>") + "</p>"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def extract_chapo(self):
|
|
||||||
return " ".join((self.extract + " ")[:60].split(" ")[:-1])
|
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
|
||||||
column_default_sort = ("date", False)
|
|
||||||
column_exclude_list = ["extract"]
|
|
||||||
column_filters = ["representative.name", "subject", "date"]
|
|
||||||
|
|
||||||
|
|
||||||
admin.add_view(AdminView(StanceModel, db.session, name="Stance", category="CRUD"))
|
|
|
@ -9,17 +9,16 @@ from app.model.model import Model, View
|
||||||
class TypeModel(db.Model, Model):
|
class TypeModel(db.Model, Model):
|
||||||
__tablename__ = "type"
|
__tablename__ = "type"
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(2000))
|
code = db.Column(db.String(200))
|
||||||
slug = db.Column(db.String(2000))
|
name = db.Column(db.String(500))
|
||||||
code = db.Column(db.String(2000))
|
slug = db.Column(db.String(500))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class AdminView(View):
|
class AdminView(View):
|
||||||
column_default_sort = "name"
|
form_excluded_columns = ["slug"]
|
||||||
column_filters = ["name", "code"]
|
|
||||||
|
|
||||||
def on_model_change(self, form, model, is_created):
|
def on_model_change(self, form, model, is_created):
|
||||||
model.slug = slugify(model.name)
|
model.slug = slugify(model.name)
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
import bcrypt
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
from app import admin, db
|
||||||
|
from app.model.model import Model, View
|
||||||
|
|
||||||
|
|
||||||
|
def get_user(user_id):
|
||||||
|
return UserModel.query.get(user_id)
|
||||||
|
|
||||||
|
|
||||||
|
class UserModel(db.Model, Model):
|
||||||
|
__tablename__ = "user"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
login = db.Column(db.String(500), unique=True)
|
||||||
|
password_hash = db.Column(db.String(128))
|
||||||
|
email = db.Column(db.String(500), unique=True)
|
||||||
|
active = db.Column(db.Boolean)
|
||||||
|
admin = db.Column(db.Boolean)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def password(self):
|
||||||
|
return self.password_hash
|
||||||
|
|
||||||
|
@password.setter
|
||||||
|
def password(self, password):
|
||||||
|
self.password_hash = bcrypt.hashpw(
|
||||||
|
password.encode("utf-8"),
|
||||||
|
bcrypt.gensalt(rounds=current_app.config["BCRYPT_ROUNDS"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_password(self, password):
|
||||||
|
return bcrypt.checkpw(password.encode("utf-8"), self.password_hash)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_active(self):
|
||||||
|
return self.active or False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_anonymous(self):
|
||||||
|
return self.id is None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_authenticated(self):
|
||||||
|
return self.id is not None
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return str(self.id)
|
||||||
|
|
||||||
|
|
||||||
|
class AdminView(View):
|
||||||
|
column_default_sort = "login"
|
||||||
|
column_exclude_list = ["password_hash", ]
|
||||||
|
|
||||||
|
def on_model_change(self, form, model, is_created):
|
||||||
|
if len(form.password_hash.data) < 128:
|
||||||
|
model.password = form.password_hash.data
|
||||||
|
|
||||||
|
|
||||||
|
admin.add_view(AdminView(UserModel, db.session, name="User"))
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
from app import admin
|
from app import admin
|
||||||
from app.controller.admin import admin_routes
|
from app.controller.admin import admin_routes
|
||||||
from app.controller.api.country import CountriesApi, CountryApi
|
|
||||||
from app.controller.api.representative import RepresentativesApi, RepresentativeApi
|
from app.controller.api.representative import RepresentativesApi, RepresentativeApi
|
||||||
from app.controller.core import Core
|
from app.controller.core import Core
|
||||||
|
from app.controller.representative import Representative
|
||||||
|
|
||||||
|
|
||||||
# Adding admin endpoints
|
# Adding admin endpoints
|
||||||
|
@ -14,15 +14,13 @@ for route in admin_routes:
|
||||||
# Listing normal endpoints
|
# Listing normal endpoints
|
||||||
routes = [
|
routes = [
|
||||||
("/", Core.as_view("home")),
|
("/", Core.as_view("home")),
|
||||||
("/representative/<int:representative_id>", Core.as_view("representative")),
|
|
||||||
("/about", Core.as_view("about")),
|
("/about", Core.as_view("about")),
|
||||||
("/who", Core.as_view("who")),
|
("/who", Core.as_view("who")),
|
||||||
|
("/representative/<int:representative_id>", Representative.as_view("view")),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Listing API endpoints
|
# Listing API endpoints
|
||||||
apis = [
|
apis = [
|
||||||
('/api/country', CountriesApi),
|
|
||||||
('/api/country/<country_id>', CountryApi),
|
|
||||||
('/api/representative', RepresentativesApi),
|
('/api/representative', RepresentativesApi),
|
||||||
('/api/representative/<representative_id>', RepresentativeApi),
|
('/api/representative/<representative_id>', RepresentativeApi),
|
||||||
]
|
]
|
||||||
|
|
|
@ -9,4 +9,4 @@
|
||||||
</ul>
|
</ul>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
</div>
|
</div>
|
||||||
{%endmacro%}
|
{%endmacro%}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
<li>Find a representative</li>
|
<li>Find a representative</li>
|
||||||
<li>Find a matter</li>
|
<li>Find a matter</li>
|
||||||
-->
|
-->
|
||||||
<li><a href="">{{_("Ajouter une prise de position")}}</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,4 +18,4 @@
|
||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
<hr />
|
<hr />
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<h1>{{_("Ajouter une prise de position")}}</h1>
|
||||||
|
|
||||||
|
<form method="POST" action="{{url_for('stance.add')}}">
|
||||||
|
{{g.form.hidden_tag()}}
|
||||||
|
{{g.form.representative()}}
|
||||||
|
{{g.form.matter()}}
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label>{{_("Représentant :")}}</label> <input type="text" />
|
||||||
|
<span class="field-description">{{_("Le représentant ayant pris cette position")}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label>{{_("Dossier :")}}</label> <input type="text" />
|
||||||
|
<span class="field-description">{{_("Le dossier lié à cette prise de position. Ce champ reste optionnel.")}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{render_field(g.form.date)}}
|
||||||
|
{{render_field(g.form.source_url)}}
|
||||||
|
{{render_field(g.form.extract)}}
|
||||||
|
<input type="submit" value="{{_('Ajouter')}}" class="btn" />
|
||||||
|
<a href="{{url_for('core.home')}}" class="btn">{{_("Annuler")}}</a>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
37
config.py
37
config.py
|
@ -1,37 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
"""
|
|
||||||
Minimal configuration able to run but maybe not as you want it.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
DEBUG = False
|
|
||||||
HOST = "0.0.0.0"
|
|
||||||
PORT = 5000
|
|
||||||
SECRET_KEY = "No secret key"
|
|
||||||
|
|
||||||
JINJA_ENV = {
|
|
||||||
"TRIM_BLOCKS": True,
|
|
||||||
"LSTRIP_BLOCKS": True,
|
|
||||||
}
|
|
||||||
|
|
||||||
# defining base directory
|
|
||||||
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
|
|
||||||
# defining database URI
|
|
||||||
# MySQL example
|
|
||||||
# SQLALCHEMY_DATABASE_URI = "mysql://username:password@server/db"
|
|
||||||
# SQLite example
|
|
||||||
# SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(BASE_DIR, "db.sqlite3")
|
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
||||||
|
|
||||||
# defining Babel settings
|
|
||||||
BABEL_DEFAULT_LOCALE = "fr"
|
|
||||||
|
|
||||||
# Languages available
|
|
||||||
AVAILABLE_LANGUAGES = {
|
|
||||||
"en": "English",
|
|
||||||
"fr": "Français",
|
|
||||||
}
|
|
||||||
|
|
||||||
API_PER_PAGE = 30
|
|
|
@ -1 +1 @@
|
||||||
Generic single-database configuration.
|
Single-database configuration for Flask.
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
# Logging configuration
|
# Logging configuration
|
||||||
[loggers]
|
[loggers]
|
||||||
keys = root,sqlalchemy,alembic
|
keys = root,sqlalchemy,alembic,flask_migrate
|
||||||
|
|
||||||
[handlers]
|
[handlers]
|
||||||
keys = console
|
keys = console
|
||||||
|
@ -34,6 +34,11 @@ level = INFO
|
||||||
handlers =
|
handlers =
|
||||||
qualname = alembic
|
qualname = alembic
|
||||||
|
|
||||||
|
[logger_flask_migrate]
|
||||||
|
level = INFO
|
||||||
|
handlers =
|
||||||
|
qualname = flask_migrate
|
||||||
|
|
||||||
[handler_console]
|
[handler_console]
|
||||||
class = StreamHandler
|
class = StreamHandler
|
||||||
args = (sys.stderr,)
|
args = (sys.stderr,)
|
||||||
|
|
|
@ -3,8 +3,6 @@ from __future__ import with_statement
|
||||||
import logging
|
import logging
|
||||||
from logging.config import fileConfig
|
from logging.config import fileConfig
|
||||||
|
|
||||||
from sqlalchemy import engine_from_config
|
|
||||||
from sqlalchemy import pool
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
from alembic import context
|
from alembic import context
|
||||||
|
@ -24,7 +22,8 @@ logger = logging.getLogger('alembic.env')
|
||||||
# target_metadata = mymodel.Base.metadata
|
# target_metadata = mymodel.Base.metadata
|
||||||
config.set_main_option(
|
config.set_main_option(
|
||||||
'sqlalchemy.url',
|
'sqlalchemy.url',
|
||||||
str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%'))
|
str(current_app.extensions['migrate'].db.get_engine().url).replace(
|
||||||
|
'%', '%%'))
|
||||||
target_metadata = current_app.extensions['migrate'].db.metadata
|
target_metadata = current_app.extensions['migrate'].db.metadata
|
||||||
|
|
||||||
# other values from the config, defined by the needs of env.py,
|
# other values from the config, defined by the needs of env.py,
|
||||||
|
@ -72,11 +71,7 @@ def run_migrations_online():
|
||||||
directives[:] = []
|
directives[:] = []
|
||||||
logger.info('No changes in schema detected.')
|
logger.info('No changes in schema detected.')
|
||||||
|
|
||||||
connectable = engine_from_config(
|
connectable = current_app.extensions['migrate'].db.get_engine()
|
||||||
config.get_section(config.config_ini_section),
|
|
||||||
prefix='sqlalchemy.',
|
|
||||||
poolclass=pool.NullPool,
|
|
||||||
)
|
|
||||||
|
|
||||||
with connectable.connect() as connection:
|
with connectable.connect() as connection:
|
||||||
context.configure(
|
context.configure(
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 0df00d383cb1
|
||||||
|
Revises: c968d84e9996
|
||||||
|
Create Date: 2022-05-27 21:31:07.974570
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '0df00d383cb1'
|
||||||
|
down_revision = 'c968d84e9996'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('country', sa.Column('slug', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('entity', sa.Column('slug', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('role', sa.Column('slug', sa.String(length=200), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('role', 'slug')
|
||||||
|
op.drop_column('entity', 'slug')
|
||||||
|
op.drop_column('country', 'slug')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -0,0 +1,44 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 49d256e40a4c
|
||||||
|
Revises:
|
||||||
|
Create Date: 2022-05-26 13:01:00.915135
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '49d256e40a4c'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('representative',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=200), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('user',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('login', sa.String(length=500), nullable=True),
|
||||||
|
sa.Column('password_hash', sa.String(length=128), nullable=True),
|
||||||
|
sa.Column('email', sa.String(length=500), nullable=True),
|
||||||
|
sa.Column('active', sa.Boolean(), nullable=True),
|
||||||
|
sa.Column('admin', sa.Boolean(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('email'),
|
||||||
|
sa.UniqueConstraint('login')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('user')
|
||||||
|
op.drop_table('representative')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -0,0 +1,43 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 6a205c6b23bb
|
||||||
|
Revises: bc290d035406
|
||||||
|
Create Date: 2022-05-27 11:12:44.242389
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '6a205c6b23bb'
|
||||||
|
down_revision = 'bc290d035406'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('entity',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=200), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('membership',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('representative_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('entity_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('start', sa.Date(), nullable=True),
|
||||||
|
sa.Column('end', sa.Date(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['entity_id'], ['entity.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['representative_id'], ['representative.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('membership')
|
||||||
|
op.drop_table('entity')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -1,8 +1,8 @@
|
||||||
"""empty message
|
"""empty message
|
||||||
|
|
||||||
Revision ID: ac34a07322f6
|
Revision ID: 6dcc965ab0d4
|
||||||
Revises: b83b29dc60b0
|
Revises: f448ec882889
|
||||||
Create Date: 2021-07-21 15:36:01.454538
|
Create Date: 2022-05-28 19:35:20.965988
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from alembic import op
|
from alembic import op
|
||||||
|
@ -10,19 +10,19 @@ import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = 'ac34a07322f6'
|
revision = '6dcc965ab0d4'
|
||||||
down_revision = 'b83b29dc60b0'
|
down_revision = 'f448ec882889'
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.add_column('representative', sa.Column('active', sa.Boolean(), nullable=True))
|
op.add_column('membership', sa.Column('active', sa.Boolean(), nullable=True))
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_column('representative', 'active')
|
op.drop_column('membership', 'active')
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
|
@ -1,28 +0,0 @@
|
||||||
"""empty message
|
|
||||||
|
|
||||||
Revision ID: 8b260b23ba3a
|
|
||||||
Revises: e0001237a466
|
|
||||||
Create Date: 2021-07-21 14:03:53.023739
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = '8b260b23ba3a'
|
|
||||||
down_revision = 'e0001237a466'
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.add_column('representative', sa.Column('code', sa.String(length=2000), nullable=True))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_column('representative', 'code')
|
|
||||||
# ### end Alembic commands ###
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: aa24a81be355
|
||||||
|
Revises: 0df00d383cb1
|
||||||
|
Create Date: 2022-05-28 15:52:36.923253
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'aa24a81be355'
|
||||||
|
down_revision = '0df00d383cb1'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('type',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('code', sa.String(length=200), nullable=True),
|
||||||
|
sa.Column('name', sa.String(length=200), nullable=True),
|
||||||
|
sa.Column('slug', sa.String(length=200), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.add_column('entity', sa.Column('parent_id', sa.Integer(), nullable=True))
|
||||||
|
op.add_column('entity', sa.Column('reference', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('entity', sa.Column('source', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('entity', sa.Column('type_id', sa.Integer(), nullable=True))
|
||||||
|
op.create_foreign_key(None, 'entity', 'type', ['type_id'], ['id'])
|
||||||
|
op.create_foreign_key(None, 'entity', 'entity', ['parent_id'], ['id'])
|
||||||
|
op.drop_column('membership', 'source')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('membership', sa.Column('source', mysql.VARCHAR(length=200), nullable=True))
|
||||||
|
op.drop_constraint(None, 'entity', type_='foreignkey')
|
||||||
|
op.drop_constraint(None, 'entity', type_='foreignkey')
|
||||||
|
op.drop_column('entity', 'type_id')
|
||||||
|
op.drop_column('entity', 'source')
|
||||||
|
op.drop_column('entity', 'reference')
|
||||||
|
op.drop_column('entity', 'parent_id')
|
||||||
|
op.drop_table('type')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -1,30 +0,0 @@
|
||||||
"""empty message
|
|
||||||
|
|
||||||
Revision ID: b83b29dc60b0
|
|
||||||
Revises: 8b260b23ba3a
|
|
||||||
Create Date: 2021-07-21 14:04:54.107335
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = 'b83b29dc60b0'
|
|
||||||
down_revision = '8b260b23ba3a'
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_constraint('representative_slug_key', 'representative', type_='unique')
|
|
||||||
op.create_unique_constraint(None, 'representative', ['code'])
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_constraint(None, 'representative', type_='unique')
|
|
||||||
op.create_unique_constraint('representative_slug_key', 'representative', ['slug'])
|
|
||||||
# ### end Alembic commands ###
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: bc290d035406
|
||||||
|
Revises: 49d256e40a4c
|
||||||
|
Create Date: 2022-05-26 13:29:55.124869
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'bc290d035406'
|
||||||
|
down_revision = '49d256e40a4c'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('representative', sa.Column('first_name', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('representative', sa.Column('last_name', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('representative', sa.Column('picture', sa.String(length=200), nullable=True))
|
||||||
|
op.drop_column('representative', 'name')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('representative', sa.Column('name', mysql.VARCHAR(length=200), nullable=True))
|
||||||
|
op.drop_column('representative', 'picture')
|
||||||
|
op.drop_column('representative', 'last_name')
|
||||||
|
op.drop_column('representative', 'first_name')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -0,0 +1,65 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: c968d84e9996
|
||||||
|
Revises: 6a205c6b23bb
|
||||||
|
Create Date: 2022-05-27 17:56:50.589477
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'c968d84e9996'
|
||||||
|
down_revision = '6a205c6b23bb'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('country',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=200), nullable=True),
|
||||||
|
sa.Column('official_state_name', sa.String(length=200), nullable=True),
|
||||||
|
sa.Column('alpha_2', sa.String(length=2), nullable=True),
|
||||||
|
sa.Column('alpha_3', sa.String(length=3), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('role',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=200), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.add_column('membership', sa.Column('source', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('membership', sa.Column('reference', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('membership', sa.Column('role_id', sa.Integer(), nullable=True))
|
||||||
|
op.create_foreign_key(None, 'membership', 'role', ['role_id'], ['id'])
|
||||||
|
op.add_column('representative', sa.Column('birth_date', sa.Date(), nullable=True))
|
||||||
|
op.add_column('representative', sa.Column('birth_place', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('representative', sa.Column('birth_region', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('representative', sa.Column('birth_country_id', sa.Integer(), nullable=True))
|
||||||
|
op.add_column('representative', sa.Column('job', sa.String(length=200), nullable=True))
|
||||||
|
op.add_column('representative', sa.Column('nationality_id', sa.Integer(), nullable=True))
|
||||||
|
op.create_foreign_key(None, 'representative', 'country', ['birth_country_id'], ['id'])
|
||||||
|
op.create_foreign_key(None, 'representative', 'country', ['nationality_id'], ['id'])
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_constraint(None, 'representative', type_='foreignkey')
|
||||||
|
op.drop_constraint(None, 'representative', type_='foreignkey')
|
||||||
|
op.drop_column('representative', 'nationality_id')
|
||||||
|
op.drop_column('representative', 'job')
|
||||||
|
op.drop_column('representative', 'birth_country_id')
|
||||||
|
op.drop_column('representative', 'birth_region')
|
||||||
|
op.drop_column('representative', 'birth_place')
|
||||||
|
op.drop_column('representative', 'birth_date')
|
||||||
|
op.drop_constraint(None, 'membership', type_='foreignkey')
|
||||||
|
op.drop_column('membership', 'role_id')
|
||||||
|
op.drop_column('membership', 'reference')
|
||||||
|
op.drop_column('membership', 'source')
|
||||||
|
op.drop_table('role')
|
||||||
|
op.drop_table('country')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -0,0 +1,32 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: cd76771172a8
|
||||||
|
Revises: f238158c8ad6
|
||||||
|
Create Date: 2022-05-28 17:21:55.500700
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'cd76771172a8'
|
||||||
|
down_revision = 'f238158c8ad6'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('entity', sa.Column('start', sa.Date(), nullable=True))
|
||||||
|
op.add_column('entity', sa.Column('end', sa.Date(), nullable=True))
|
||||||
|
op.add_column('entity', sa.Column('active', sa.Boolean(), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('entity', 'active')
|
||||||
|
op.drop_column('entity', 'end')
|
||||||
|
op.drop_column('entity', 'start')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -1,178 +0,0 @@
|
||||||
"""empty message
|
|
||||||
|
|
||||||
Revision ID: e0001237a466
|
|
||||||
Revises:
|
|
||||||
Create Date: 2021-07-16 19:43:05.321519
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = 'e0001237a466'
|
|
||||||
down_revision = None
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.create_table('country',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('code', sa.String(length=2000), nullable=True),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('matter',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('description', sa.Text(), nullable=True),
|
|
||||||
sa.Column('active', sa.Boolean(), nullable=True),
|
|
||||||
sa.PrimaryKeyConstraint('id'),
|
|
||||||
sa.UniqueConstraint('slug')
|
|
||||||
)
|
|
||||||
op.create_table('role',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('code', sa.String(length=2000), nullable=True),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('type',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('code', sa.String(length=2000), nullable=True),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('address',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('country_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('number', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('street', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('miscellaneous', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('city', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('zipcode', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('building', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('floor', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('stair', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('office', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('latitude', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('longitude', sa.String(length=2000), nullable=True),
|
|
||||||
sa.ForeignKeyConstraint(['country_id'], ['country.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('entity',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('code', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('picture', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('type_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('start', sa.DateTime(), nullable=True),
|
|
||||||
sa.Column('end', sa.DateTime(), nullable=True),
|
|
||||||
sa.Column('country_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('parent_id', sa.Integer(), nullable=True),
|
|
||||||
sa.ForeignKeyConstraint(['country_id'], ['country.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['parent_id'], ['entity.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['type_id'], ['type.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('representative',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('picture', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('nationality_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('sex', sa.String(length=1), nullable=True),
|
|
||||||
sa.Column('birth_date', sa.Date(), nullable=True),
|
|
||||||
sa.Column('birth_place', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('job', sa.String(length=2000), nullable=True),
|
|
||||||
sa.ForeignKeyConstraint(['nationality_id'], ['country.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id'),
|
|
||||||
sa.UniqueConstraint('slug')
|
|
||||||
)
|
|
||||||
op.create_table('contact',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('representative_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('address_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('value', sa.String(length=2000), nullable=True),
|
|
||||||
sa.ForeignKeyConstraint(['address_id'], ['address.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['representative_id'], ['representative.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('membership',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('representative_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('role_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('start', sa.DateTime(), nullable=True),
|
|
||||||
sa.Column('end', sa.DateTime(), nullable=True),
|
|
||||||
sa.Column('entity_id', sa.Integer(), nullable=True),
|
|
||||||
sa.ForeignKeyConstraint(['entity_id'], ['entity.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['representative_id'], ['representative.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['role_id'], ['role.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('recommendation',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('matter_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('entity_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('name', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('slug', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('code', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('date', sa.Date(), nullable=True),
|
|
||||||
sa.Column('description', sa.Text(), nullable=True),
|
|
||||||
sa.Column('value', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('weight', sa.Integer(), nullable=True),
|
|
||||||
sa.ForeignKeyConstraint(['entity_id'], ['entity.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['matter_id'], ['matter.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id'),
|
|
||||||
sa.UniqueConstraint('slug')
|
|
||||||
)
|
|
||||||
op.create_table('stance',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('representative_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('matter_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('date', sa.DateTime(), nullable=True),
|
|
||||||
sa.Column('subject', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('extract', sa.Text(), nullable=True),
|
|
||||||
sa.Column('source_url', sa.String(length=2000), nullable=True),
|
|
||||||
sa.Column('active', sa.Boolean(), nullable=True),
|
|
||||||
sa.ForeignKeyConstraint(['matter_id'], ['matter.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['representative_id'], ['representative.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
op.create_table('decision',
|
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('representative_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('recommendation_id', sa.Integer(), nullable=True),
|
|
||||||
sa.Column('value', sa.String(length=2000), nullable=True),
|
|
||||||
sa.ForeignKeyConstraint(['recommendation_id'], ['recommendation.id'], ),
|
|
||||||
sa.ForeignKeyConstraint(['representative_id'], ['representative.id'], ),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_table('decision')
|
|
||||||
op.drop_table('stance')
|
|
||||||
op.drop_table('recommendation')
|
|
||||||
op.drop_table('membership')
|
|
||||||
op.drop_table('contact')
|
|
||||||
op.drop_table('representative')
|
|
||||||
op.drop_table('entity')
|
|
||||||
op.drop_table('address')
|
|
||||||
op.drop_table('type')
|
|
||||||
op.drop_table('role')
|
|
||||||
op.drop_table('matter')
|
|
||||||
op.drop_table('country')
|
|
||||||
# ### end Alembic commands ###
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: f238158c8ad6
|
||||||
|
Revises: aa24a81be355
|
||||||
|
Create Date: 2022-05-28 16:41:01.047513
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'f238158c8ad6'
|
||||||
|
down_revision = 'aa24a81be355'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column('entity', 'name',
|
||||||
|
existing_type=mysql.VARCHAR(length=200),
|
||||||
|
type_=sa.String(length=500),
|
||||||
|
existing_nullable=True)
|
||||||
|
op.alter_column('entity', 'slug',
|
||||||
|
existing_type=mysql.VARCHAR(length=200),
|
||||||
|
type_=sa.String(length=500),
|
||||||
|
existing_nullable=True)
|
||||||
|
op.alter_column('type', 'name',
|
||||||
|
existing_type=mysql.VARCHAR(length=200),
|
||||||
|
type_=sa.String(length=500),
|
||||||
|
existing_nullable=True)
|
||||||
|
op.alter_column('type', 'slug',
|
||||||
|
existing_type=mysql.VARCHAR(length=200),
|
||||||
|
type_=sa.String(length=500),
|
||||||
|
existing_nullable=True)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column('type', 'slug',
|
||||||
|
existing_type=sa.String(length=500),
|
||||||
|
type_=mysql.VARCHAR(length=200),
|
||||||
|
existing_nullable=True)
|
||||||
|
op.alter_column('type', 'name',
|
||||||
|
existing_type=sa.String(length=500),
|
||||||
|
type_=mysql.VARCHAR(length=200),
|
||||||
|
existing_nullable=True)
|
||||||
|
op.alter_column('entity', 'slug',
|
||||||
|
existing_type=sa.String(length=500),
|
||||||
|
type_=mysql.VARCHAR(length=200),
|
||||||
|
existing_nullable=True)
|
||||||
|
op.alter_column('entity', 'name',
|
||||||
|
existing_type=sa.String(length=500),
|
||||||
|
type_=mysql.VARCHAR(length=200),
|
||||||
|
existing_nullable=True)
|
||||||
|
# ### end Alembic commands ###
|
|
@ -0,0 +1,45 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: f448ec882889
|
||||||
|
Revises: cd76771172a8
|
||||||
|
Create Date: 2022-05-28 18:53:26.059567
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'f448ec882889'
|
||||||
|
down_revision = 'cd76771172a8'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('source',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=200), nullable=True),
|
||||||
|
sa.Column('slug', sa.String(length=200), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('representative_origin',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('representative_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('source_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('reference', sa.String(length=200), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['representative_id'], ['representative.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['source_id'], ['source.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.add_column('role', sa.Column('code', sa.String(length=200), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('role', 'code')
|
||||||
|
op.drop_table('representative_origin')
|
||||||
|
op.drop_table('source')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -1,5 +0,0 @@
|
||||||
[build-system]
|
|
||||||
requires = ["setuptools", "wheel"]
|
|
||||||
|
|
||||||
[tool.black]
|
|
||||||
exclude = "migrations/"
|
|
|
@ -1,3 +0,0 @@
|
||||||
black
|
|
||||||
pytest
|
|
||||||
pytest-black
|
|
|
@ -7,5 +7,7 @@ flask_migrate
|
||||||
flask_restful
|
flask_restful
|
||||||
flask_sqlalchemy
|
flask_sqlalchemy
|
||||||
flask_wtf
|
flask_wtf
|
||||||
|
python-dotenv
|
||||||
python-slugify
|
python-slugify
|
||||||
requests
|
requests
|
||||||
|
mysqlclient
|
||||||
|
|
32
server.py
32
server.py
|
@ -13,38 +13,34 @@ from app.routes import apis, routes
|
||||||
from command import commands
|
from command import commands
|
||||||
|
|
||||||
|
|
||||||
app = flask.Flask(__name__, template_folder="app/view")
|
application = flask.Flask(__name__, template_folder="app/view")
|
||||||
app.config.from_object("config")
|
application.config.from_object("settings")
|
||||||
try:
|
|
||||||
app.config.from_object(f"config-{app.config['ENV']}")
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
if "JINJA_ENV" in app.config:
|
if "JINJA_ENV" in application.config:
|
||||||
app.jinja_env.trim_blocks = app.config["JINJA_ENV"]["TRIM_BLOCKS"]
|
application.jinja_env.trim_blocks = application.config["JINJA_ENV"]["TRIM_BLOCKS"]
|
||||||
app.jinja_env.lstrip_blocks = app.config["JINJA_ENV"]["LSTRIP_BLOCKS"]
|
application.jinja_env.lstrip_blocks = application.config["JINJA_ENV"]["LSTRIP_BLOCKS"]
|
||||||
|
|
||||||
# Loading routes
|
# Loading routes
|
||||||
for route in routes:
|
for route in routes:
|
||||||
if len(route) < 3:
|
if len(route) < 3:
|
||||||
app.add_url_rule(route[0], route[1].__name__, route[1], methods=["GET"])
|
application.add_url_rule(route[0], route[1].__name__, route[1], methods=["GET"])
|
||||||
else:
|
else:
|
||||||
app.add_url_rule(route[0], route[1].__name__, route[1], methods=route[2])
|
application.add_url_rule(route[0], route[1].__name__, route[1], methods=route[2])
|
||||||
# Loading API routes
|
# Loading API routes
|
||||||
for route in apis:
|
for route in apis:
|
||||||
api.add_resource(route[1], route[0])
|
api.add_resource(route[1], route[0])
|
||||||
|
|
||||||
# Initialisation of extensions
|
# Initialisation of extensions
|
||||||
admin.init_app(app)
|
admin.init_app(application)
|
||||||
api.init_app(app)
|
api.init_app(application)
|
||||||
babel.init_app(app)
|
babel.init_app(application)
|
||||||
db.init_app(app)
|
db.init_app(application)
|
||||||
login_manager.init_app(app)
|
login_manager.init_app(application)
|
||||||
migrate.init_app(app, db)
|
migrate.init_app(application, db)
|
||||||
|
|
||||||
# Manage commands
|
# Manage commands
|
||||||
for command in commands:
|
for command in commands:
|
||||||
app.cli.add_command(command)
|
application.cli.add_command(command)
|
||||||
|
|
||||||
|
|
||||||
# Manage locale
|
# Manage locale
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
DEBUG = os.environ.get("DEBUG", False)
|
||||||
|
SECRET_KEY = os.environ.get("SECRET_KEY", "Choose a secret key")
|
||||||
|
JINJA_ENV = {
|
||||||
|
"TRIM_BLOCKS": True,
|
||||||
|
"LSTRIP_BLOCKS": True,
|
||||||
|
}
|
||||||
|
SQLALCHEMY_DATABASE_URI = os.environ.get("SQLALCHEMY_DATABASE_URI", "sqlite:///" + os.path.join(BASE_DIR, "db.sqlite3"))
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
BCRYPT_ROUNDS = os.environ.get("BCRYPT_ROUNDS", 15)
|
||||||
|
BABEL_DEFAULT_LOCALE = os.environ.get("BABEL_DEFAULT_LOCALE", "fr")
|
||||||
|
AVAILABLE_LANGUAGES = {
|
||||||
|
"fr": "Français",
|
||||||
|
"en": "English",
|
||||||
|
}
|
||||||
|
API_PER_PAGE = int(os.environ.get("API_PER_PAGE", 10))
|
Loading…
Reference in New Issue