utils-flask-sqlalchemy 0.3.2__tar.gz → 0.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {utils-flask-sqlalchemy-0.3.2/src/utils_flask_sqlalchemy.egg-info → utils-flask-sqlalchemy-0.3.4}/PKG-INFO +1 -1
  2. utils-flask-sqlalchemy-0.3.4/VERSION +1 -0
  3. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/requirements.in +1 -0
  4. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/generic.py +33 -19
  5. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/response.py +0 -1
  6. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/schema.py +6 -0
  7. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/serializers.py +2 -9
  8. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/tests/test_schema.py +19 -1
  9. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4/src/utils_flask_sqlalchemy.egg-info}/PKG-INFO +1 -1
  10. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqlalchemy.egg-info/requires.txt +1 -0
  11. utils-flask-sqlalchemy-0.3.2/VERSION +0 -1
  12. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/LICENSE +0 -0
  13. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/MANIFEST.in +0 -0
  14. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/README.md +0 -0
  15. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/pyproject.toml +0 -0
  16. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/setup.cfg +0 -0
  17. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/setup.py +0 -0
  18. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/__init__.py +0 -0
  19. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/commands.py +0 -0
  20. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/errors.py +0 -0
  21. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/migrations/__init__.py +0 -0
  22. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/migrations/utils.py +0 -0
  23. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/migrations/versions/3842a6d800a0_sql_utils.py +0 -0
  24. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/migrations/versions/__init__.py +0 -0
  25. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/migrations/versions/ba207b468e31_create_fr_numeric_collation.py +0 -0
  26. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/tests/__init__.py +0 -0
  27. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/tests/fixtures.py +0 -0
  28. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/tests/plugin.py +0 -0
  29. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/tests/test_serializers.py +0 -0
  30. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/tests/utils.py +0 -0
  31. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqla/utils.py +0 -0
  32. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqlalchemy.egg-info/SOURCES.txt +0 -0
  33. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqlalchemy.egg-info/dependency_links.txt +0 -0
  34. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqlalchemy.egg-info/entry_points.txt +0 -0
  35. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/src/utils_flask_sqlalchemy.egg-info/top_level.txt +0 -0
  36. {utils-flask-sqlalchemy-0.3.2 → utils-flask-sqlalchemy-0.3.4}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: utils-flask-sqlalchemy
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Python lib of tools for Flask and SQLAlchemy
5
5
  Home-page: https://github.com/PnX-SI/Utils-Flask-SQLAlchemy
6
6
  Maintainer: Parcs nationaux des Écrins et des Cévennes
@@ -0,0 +1 @@
1
+ 0.3.4
@@ -3,3 +3,4 @@ flask-sqlalchemy
3
3
  flask-migrate
4
4
  marshmallow
5
5
  python-dateutil
6
+ sqlalchemy>=1.3,<2
@@ -1,12 +1,13 @@
1
1
  from itertools import chain
2
2
  from warnings import warn
3
3
 
4
- from sqlalchemy import MetaData
4
+ from dateutil import parser
5
5
  from flask_sqlalchemy import SQLAlchemy
6
- from .errors import UtilsSqlaError
6
+ from sqlalchemy import MetaData
7
7
  from sqlalchemy.dialects.postgresql import UUID
8
- from sqlalchemy.types import Integer, Date, DateTime, Numeric, Boolean
9
- from dateutil import parser
8
+ from sqlalchemy.types import Boolean, Date, DateTime, Integer, Numeric
9
+
10
+ from .errors import UtilsSqlaError
10
11
 
11
12
 
12
13
  def testDataType(value, sqlType, paramName):
@@ -198,10 +199,12 @@ class GenericQuery:
198
199
  if param_name.startswith("filter_d_"):
199
200
  col = self.view.tableDef.columns[param_name[12:]]
200
201
  col_type = col.type.__class__.__name__
201
- test_type = testDataType(param_value, DateTime, col)
202
+ test_type = testDataType(param_value, DateTime, col) and testDataType(
203
+ param_value, Integer, col
204
+ )
202
205
  if test_type:
203
206
  raise UtilsSqlaError(message=test_type)
204
- if col_type in ("Date", "DateTime", "TIMESTAMP"):
207
+ if col_type in ("Date", "DateTime", "TIMESTAMP", "INTEGER"):
205
208
  if param_name.startswith("filter_d_up_"):
206
209
  query = query.filter(col >= param_value)
207
210
  if param_name.startswith("filter_d_lo_"):
@@ -225,7 +228,7 @@ class GenericQuery:
225
228
  # Ordonnancement
226
229
  # L'ordonnancement se base actuellement sur une seule colonne
227
230
  # et prend la forme suivante : nom_colonne[:ASC|DESC]
228
- if parameters.get("orderby", None).replace(" ", ""):
231
+ if parameters.get("orderby", "").replace(" ", ""):
229
232
  order_by = parameters.get("orderby")
230
233
  col, *sort = order_by.split(":")
231
234
  if col in self.view.tableDef.columns.keys():
@@ -235,26 +238,37 @@ class GenericQuery:
235
238
  return query.order_by(ordel_col)
236
239
  return query
237
240
 
238
- def query(self):
241
+ def raw_query(self, process_filter=True):
239
242
  """
240
- Lance la requete et retourne l'objet sqlalchemy
243
+ Renvoie la requete 'brute' (sans .all)
244
+ - process_filter: application des filtres (et du sort)
241
245
  """
246
+
242
247
  q = self.DB.session.query(self.view.tableDef)
243
- nb_result_without_filter = q.count()
248
+
249
+ if not process_filter:
250
+ return q
244
251
 
245
252
  if self.filters:
246
253
  unordered_q = self.build_query_filters(q, self.filters)
247
254
  q = self.build_query_order(unordered_q, self.filters)
248
- nb_results = unordered_q.count()
249
- else:
250
- nb_results = q.count()
251
255
 
252
- # Si la limite spécifiée est égale à -1
253
- # les paramètres limit et offset ne sont pas pris en compte
254
- if self.limit == -1:
255
- data = q.all()
256
- else:
257
- data = q.limit(self.limit).offset(self.offset * self.limit).all()
256
+ if self.limit != -1:
257
+ q.limit(self.limit).offset(self.offset * self.limit)
258
+
259
+ return q
260
+
261
+ def query(self):
262
+ """
263
+ Lance la requete et retourne l'objet sqlalchemy
264
+ """
265
+ q = self.raw_query(process_filter=False)
266
+ nb_result_without_filter = q.count()
267
+
268
+ q = self.raw_query()
269
+ nb_results = q.count() if self.filters else nb_result_without_filter
270
+
271
+ data = q.all()
258
272
 
259
273
  return data, nb_result_without_filter, nb_results
260
274
 
@@ -75,7 +75,6 @@ def csv_resp(fn):
75
75
 
76
76
 
77
77
  def to_csv_resp(filename, data, columns, separator=";"):
78
-
79
78
  headers = Headers()
80
79
  headers.add("Content-Type", "text/plain")
81
80
  headers.add("Content-Disposition", "attachment", filename="export_%s.csv" % filename)
@@ -23,6 +23,12 @@ class SmartRelationshipsMixin:
23
23
  nested_fields.add(name)
24
24
  elif field.metadata.get("exclude", False):
25
25
  excluded_fields.add(name)
26
+ elif (
27
+ hasattr(self.opts, "model")
28
+ and hasattr(self.opts.model.__mapper__.column_attrs, name)
29
+ and getattr(self.opts.model.__mapper__.column_attrs, name).deferred
30
+ ):
31
+ excluded_fields.add(name)
26
32
  else:
27
33
  included_fields.add(name)
28
34
 
@@ -369,8 +369,7 @@ def get_serializable_decorator(fields=[], exclude=[], stringify=True):
369
369
  # gestion des relationships
370
370
  frel = get_cls_db_relationships()
371
371
 
372
- for (rel, uselist, Model) in frel:
373
-
372
+ for rel, uselist, Model in frel:
374
373
  if rel not in dict_in:
375
374
  continue
376
375
 
@@ -409,13 +408,7 @@ def get_serializable_decorator(fields=[], exclude=[], stringify=True):
409
408
  v_obj = []
410
409
 
411
410
  for data in values:
412
-
413
- id_value = data.get(id_field_name)
414
-
415
- # si id_value est null
416
- # creation -> on supprime id_value
417
- if not id_value:
418
- data.pop(id_field_name)
411
+ id_value = data.pop(id_field_name, None)
419
412
 
420
413
  res = (
421
414
  # si on a une id -> on recupère dans la liste preload_res_with_ids
@@ -4,7 +4,7 @@ import marshmallow as ma
4
4
  from marshmallow.fields import Nested
5
5
  from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, auto_field
6
6
  from sqlalchemy import Column, Integer, String, ForeignKey
7
- from sqlalchemy.orm import relationship
7
+ from sqlalchemy.orm import relationship, deferred
8
8
  from sqlalchemy.ext.hybrid import hybrid_property
9
9
  from flask_sqlalchemy import SQLAlchemy
10
10
 
@@ -388,3 +388,21 @@ class TestSmartRelationshipsMixin:
388
388
  },
389
389
  },
390
390
  )
391
+
392
+ def test_deferred_field(self):
393
+ class DeferredModel(db.Model):
394
+ pk = db.Column(db.Integer, primary_key=True)
395
+ a = db.Column(db.String)
396
+ b = deferred(db.Column(db.String))
397
+
398
+ class DeferredSchema(SmartRelationshipsMixin, SQLAlchemyAutoSchema):
399
+ class Meta:
400
+ model = DeferredModel
401
+
402
+ d = DeferredModel(pk=1, a="A", b="B")
403
+
404
+ TestCase().assertDictEqual(DeferredSchema().dump(d), {"pk": 1, "a": "A"})
405
+ TestCase().assertDictEqual(
406
+ DeferredSchema(only=["+b"]).dump(d), {"pk": 1, "a": "A", "b": "B"}
407
+ )
408
+ TestCase().assertDictEqual(DeferredSchema(only=["b"]).dump(d), {"b": "B"})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: utils-flask-sqlalchemy
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Python lib of tools for Flask and SQLAlchemy
5
5
  Home-page: https://github.com/PnX-SI/Utils-Flask-SQLAlchemy
6
6
  Maintainer: Parcs nationaux des Écrins et des Cévennes
@@ -3,6 +3,7 @@ flask-sqlalchemy
3
3
  flask-migrate
4
4
  marshmallow
5
5
  python-dateutil
6
+ sqlalchemy<2,>=1.3
6
7
 
7
8
  [tests]
8
9
  pytest
@@ -1 +0,0 @@
1
- 0.3.2