Skip to content

Commit 2f937ff

Browse files
authored
Merge pull request #311 from PnX-SI/dev
v0.99.4-dev
2 parents 4c486ac + df56257 commit 2f937ff

71 files changed

Lines changed: 5052 additions & 3986 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.99.3-dev
1+
0.99.4-dev

backend/dev-requirements.txt

Lines changed: 0 additions & 22 deletions
This file was deleted.

backend/gncitizen/core/badges/routes.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
from flask import Flask, request, Blueprint, Response, jsonify, current_app
2-
from gncitizen.utils.sqlalchemy import json_resp
3-
from gncitizen.core.observations.models import ObservationModel
1+
from calendar import monthrange
2+
from datetime import datetime, timedelta
3+
4+
from flask import Blueprint, Flask, Response, current_app, jsonify, request
5+
from sqlalchemy.sql.expression import func
6+
from utils_flask_sqla.response import json_resp
7+
48
from gncitizen.core.commons.models import ProgramsModel
5-
from gncitizen.core.users.models import UserModel
9+
from gncitizen.core.observations.models import ObservationModel
610
from gncitizen.core.taxonomy.models import Taxref
7-
from sqlalchemy.sql.expression import func
8-
from datetime import date, datetime, timedelta
9-
from calendar import monthrange
11+
from gncitizen.core.users.models import UserModel
1012
from server import db
1113

1214
badges_api = Blueprint("badges", __name__)
@@ -35,7 +37,8 @@ def get_rewards(id):
3537
total_obs = total_obs + item.nb_obs
3638
taxon_classe_query = (
3739
db.session.query(
38-
Taxref.classe.label("classe"), func.count(Taxref.famille).label("nb_obs")
40+
Taxref.classe.label("classe"),
41+
func.count(Taxref.famille).label("nb_obs"),
3942
)
4043
.join(ObservationModel, Taxref.cd_nom == ObservationModel.cd_nom)
4144
.filter(ObservationModel.id_role == id)
@@ -46,7 +49,8 @@ def get_rewards(id):
4649

4750
taxon_famille_query = (
4851
db.session.query(
49-
Taxref.famille.label("famille"), func.count(Taxref.famille).label("nb_obs")
52+
Taxref.famille.label("famille"),
53+
func.count(Taxref.famille).label("nb_obs"),
5054
)
5155
.join(ObservationModel, Taxref.cd_nom == ObservationModel.cd_nom)
5256
.filter(ObservationModel.id_role == id)
@@ -59,7 +63,9 @@ def get_rewards(id):
5963
user = UserModel.query.filter(UserModel.id_user == id).one()
6064
result = user.as_secured_dict(True)
6165
user_date_create = result["timestamp_create"]
62-
user_date_create = datetime.strptime(user_date_create, "%Y-%m-%dT%H:%M:%S.%f")
66+
user_date_create = datetime.strptime(
67+
user_date_create, "%Y-%m-%dT%H:%M:%S.%f"
68+
)
6369

6470
for reward in rewards:
6571

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,23 @@
11
#!/usr/bin/python3
22
# -*- coding:utf-8 -*-
3-
4-
import json
5-
import urllib.parse
6-
73
import requests
8-
9-
from flask import Blueprint, current_app, request, flash
10-
from flask_admin.contrib.geoa import ModelView
11-
from flask_admin.form import SecureForm
4+
from flask import current_app, flash
5+
from flask_admin.contrib.sqla.view import ModelView
126
from flask_admin.form.upload import FileUploadField
13-
from flask_ckeditor import CKEditorField
14-
15-
from geoalchemy2.shape import from_shape
16-
from geojson import FeatureCollection
17-
from shapely.geometry import MultiPolygon, asShape
7+
from flask_admin.model.form import InlineFormAdmin
8+
from flask_ckeditor import CKEditorField
189
from wtforms import SelectField
1910

20-
import json
21-
from flask_admin.contrib.sqla.view import ModelView
22-
from jinja2 import Markup
23-
24-
from gncitizen.core.users.models import UserModel
2511
from gncitizen.core.sites.models import CorProgramSiteTypeModel
26-
from gncitizen.utils.env import admin, MEDIA_DIR
27-
from gncitizen.utils.errors import GeonatureApiError
28-
from gncitizen.utils.sqlalchemy import json_resp
29-
from server import db
30-
31-
from .models import ProgramsModel
3212
from gncitizen.core.taxonomy.models import BibListes
33-
import os
13+
from gncitizen.utils.admin import (
14+
CustomJSONField,
15+
CustomTileView,
16+
json_formatter,
17+
)
18+
from gncitizen.utils.env import MEDIA_DIR
3419

35-
36-
def json_formatter(view, context, model, name):
37-
value = getattr(model, name)
38-
json_value = json.dumps(value, ensure_ascii=False, indent=2)
39-
return Markup("<pre>{}</pre>".format(json_value))
20+
logger = current_app.logger
4021

4122

4223
def taxonomy_lists():
@@ -64,30 +45,31 @@ def taxonomy_lists():
6445
return taxonomy_lists
6546

6647

67-
from flask_admin.model.form import InlineFormAdmin
68-
69-
7048
class CorProgramSiteTypeModelInlineForm(InlineFormAdmin):
7149
form_columns = ("site_type",)
7250

7351

7452
class ProjectView(ModelView):
7553
form_overrides = {"long_desc": CKEditorField}
7654
create_template = "edit.html"
77-
create_template = "edit.html"
7855
edit_template = "edit.html"
7956
form_excluded_columns = ["timestamp_create", "timestamp_update"]
80-
column_exclude_list = ['long_desc','short_desc']
57+
column_exclude_list = ["long_desc", "short_desc"]
8158

8259

8360
class ProgramView(ModelView):
84-
# form_base_class = SecureForm
8561
form_overrides = {"long_desc": CKEditorField, "taxonomy_list": SelectField}
8662
form_args = {"taxonomy_list": {"choices": taxonomy_lists(), "coerce": int}}
8763
create_template = "edit.html"
8864
edit_template = "edit.html"
8965
form_excluded_columns = ["timestamp_create", "timestamp_update"]
90-
column_exclude_list = ['long_desc','form_message','short_desc','image','logo']
66+
column_exclude_list = [
67+
"long_desc",
68+
"form_message",
69+
"short_desc",
70+
"image",
71+
"logo",
72+
]
9173
inline_models = [
9274
(
9375
CorProgramSiteTypeModel,
@@ -100,22 +82,27 @@ class ProgramView(ModelView):
10082

10183

10284
class CustomFormView(ModelView):
85+
form_overrides = {"json_schema": CustomJSONField}
10386
column_formatters = {
10487
"json_schema": json_formatter,
10588
}
10689

10790

10891
class UserView(ModelView):
10992
column_exclude_list = ["password"]
110-
form_excluded_columns = ["timestamp_create", "timestamp_update", "password"]
93+
form_excluded_columns = [
94+
"timestamp_create",
95+
"timestamp_update",
96+
"password",
97+
]
11198

11299

113100
def get_geom_file_path(obj, file_data):
114101
return "geometries/{}".format(file_data.filename)
115102

116103

117-
class GeometryView(ModelView):
118-
column_exclude_list = ["geom"]
104+
class GeometryView(CustomTileView):
105+
# column_exclude_list = ["geom"]
119106
form_excluded_columns = ["timestamp_create", "timestamp_update"]
120107
form_overrides = dict(geom_file=FileUploadField)
121108
form_args = dict(
@@ -124,7 +111,7 @@ class GeometryView(ModelView):
124111
description="""
125112
Le fichier contenant la géométrie de la zone doit être au format geojson ou kml.<br>
126113
Seules les types Polygon et MultiPolygon (ou MultiGeometry pour kml) sont acceptées.<br>
127-
Les fichiers GeoJson fournis devront être en projection WGS84 (donc SRID 4326)
114+
Les fichiers GeoJson fournis devront être en projection WGS84 (donc SRID 4326)
128115
et respecter le format "FeatureCollection" tel que présenté ici :
129116
https://tools.ietf.org/html/rfc7946#section-1.5.
130117
""",
@@ -135,9 +122,13 @@ class GeometryView(ModelView):
135122
)
136123

137124
def on_model_change(self, form, model, is_created):
138-
model.set_geom_from_geom_file()
125+
logger.debug(f"data {form.data}")
126+
logger.debug(f"geom_file {form.geom_file}")
127+
logger.debug(f"model {dir(model)}")
128+
if form.data["geom_file"]:
129+
model.set_geom_from_geom_file()
139130

140131
def handle_view_exception(self, exc):
141132
flash("Une erreur s'est produite ({})".format(exc), "error")
133+
logger.critical(exc)
142134
return True
143-

backend/gncitizen/core/commons/models.py

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
#!/usr/bin/python3
22
# -*- coding: utf-8 -*-
33

4-
from datetime import datetime
4+
import json
5+
import os
56
import uuid
7+
import xml.etree.ElementTree as ET
8+
from datetime import datetime
69

710
from geoalchemy2 import Geometry
11+
from geoalchemy2.functions import (
12+
ST_GeomFromGeoJSON,
13+
ST_GeomFromKML,
14+
ST_SetSRID,
15+
)
816
from sqlalchemy import ForeignKey
9-
from sqlalchemy.sql import expression
17+
from sqlalchemy.dialects.postgresql import JSONB, UUID
1018
from sqlalchemy.ext.declarative import declared_attr
1119
from sqlalchemy.orm import relationship
12-
from sqlalchemy.dialects.postgresql import JSONB, UUID
20+
from sqlalchemy.sql import expression
21+
from utils_flask_sqla_geo.serializers import geoserializable, serializable
1322

1423
from gncitizen.core.taxonomy.models import BibListes
15-
from gncitizen.utils.env import db, MEDIA_DIR
16-
from gncitizen.utils.sqlalchemy import serializable, geoserializable
17-
import os
24+
from gncitizen.utils.env import MEDIA_DIR, db
1825

1926

2027
class TimestampMixinModel(object):
@@ -65,12 +72,9 @@ def __repr__(self):
6572
return self.name
6673

6774

68-
from geoalchemy2.functions import ST_GeomFromKML, ST_GeomFromGeoJSON, ST_SetSRID
69-
import json
70-
import xml.etree.ElementTree as ET
71-
7275

7376
@serializable
77+
@geoserializable
7478
class GeometryModel(TimestampMixinModel, db.Model):
7579
"""Table des géométries associées aux programmes"""
7680

@@ -104,7 +108,9 @@ def set_geom_from_geom_file(self):
104108
if abs(x) > 180 or abs(y) > 180:
105109
raise Exception("Mauvais système de projection")
106110
# Convert Geo
107-
self.geom = ST_SetSRID(ST_GeomFromGeoJSON(json.dumps(json_geom)), 4326)
111+
self.geom = ST_SetSRID(
112+
ST_GeomFromGeoJSON(json.dumps(json_geom)), 4326
113+
)
108114
elif ext == ".kml":
109115
kml_root = ET.fromstring(geo_data)
110116
kml_geom_elt = None
@@ -119,7 +125,9 @@ def set_geom_from_geom_file(self):
119125
raise Exception(gnc_invalid_err_message)
120126
if kml_geom_elt is None:
121127
raise Exception(gnc_invalid_err_message)
122-
kml_geom = ET.tostring(kml_geom_elt, encoding="unicode", method="xml")
128+
kml_geom = ET.tostring(
129+
kml_geom_elt, encoding="unicode", method="xml"
130+
)
123131
self.geom = ST_GeomFromKML(kml_geom) # KML is always 4326 srid
124132

125133
def __repr__(self):
@@ -169,11 +177,16 @@ class ProgramsModel(TimestampMixinModel, db.Model):
169177
image = db.Column(db.String(250))
170178
logo = db.Column(db.String(250))
171179
id_module = db.Column(
172-
db.Integer, ForeignKey(TModules.id_module), nullable=False, default=1,
180+
db.Integer,
181+
ForeignKey(TModules.id_module),
182+
nullable=False,
183+
default=1,
173184
)
174185
module = relationship("TModules")
175186
taxonomy_list = db.Column(db.Integer, nullable=True)
176-
is_active = db.Column(db.Boolean(), server_default=expression.true(), default=True)
187+
is_active = db.Column(
188+
db.Boolean(), server_default=expression.true(), default=True
189+
)
177190
id_geom = db.Column(
178191
db.Integer, db.ForeignKey(GeometryModel.id_geom), nullable=False
179192
)
@@ -187,7 +200,9 @@ class ProgramsModel(TimestampMixinModel, db.Model):
187200
def get_geofeature(self, recursif=True, columns=None):
188201
geometry = to_shape(self.geometry.geom)
189202
feature = Feature(
190-
id=self.id_program, geometry=geometry, properties=self.as_dict(True),
203+
id=self.id_program,
204+
geometry=geometry,
205+
properties=self.as_dict(True),
191206
)
192207
return feature
193208

@@ -196,10 +211,8 @@ def __repr__(self):
196211

197212

198213
@serializable
199-
@geoserializable
200214
class MediaModel(TimestampMixinModel, db.Model):
201-
"""Table des Programmes de GeoNature-citizen
202-
"""
215+
"""Table des Programmes de GeoNature-citizen"""
203216

204217
__tablename__ = "t_medias"
205218
__table_args__ = {"schema": "gnc_core"}

0 commit comments

Comments
 (0)