Skip to content

Commit

Permalink
feat(SmartRelationshipsMixin): support "-" in only
Browse files Browse the repository at this point in the history
Add "-" special value to only to remove all default fields from
serialization when you want to serialize only relationships.
  • Loading branch information
bouttier committed Oct 13, 2024
1 parent e11d81a commit bbf3d9d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 6 deletions.
21 changes: 15 additions & 6 deletions src/utils_flask_sqla/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ class SmartRelationshipsMixin:
* Nested, RelatedList and Related fields
* all fields with exclude=True in their metadata (e.g. ``fields.String(metadata={'exclude': True})``)
Adding only Nested fields to ``only`` will not exclude others fields and serialize specified Nested fields.
Adding exclude=True fields to ``only`` will serialize only specified fields (default marshmallow behaviour).
You can use '+field_name' syntax on `only` to serialize default excluded fields (with metadata exclude = True) without other fields.
* For SQLAlchemyAutoSchema, all deffered columns
Default marshmallow behaviour is to serialize only fields specified in ``only``. This mixin add these:
* If they are only Nested fields in ``only``, they are added to serialized fields *along with* default serialized fields.
* To serialize Nested fields only and not default serialized fields, add ``"-"`` special value to ``only``.
* To add excluded fields (through metadata or deffered fields) to the serialization *in addition* to default serialized fields,
use '+field_name' syntax.
Examples :
Expand All @@ -25,9 +30,12 @@ class FooSchema(SmartRelationshipsMixin):
relationship = fields.Nested(OtherSchema) # or field.RelatedList() / field.Related()
FooSchema().dump() -> {"id": 1, "name": "toto" }
FooSchema(only=["+default_excluded_field"]).dump() -> {"id": 1, "name": "toto", default_excluded_field: "test" }
FooSchema(only=["relationship"]).dump() -> {"id": 1, "name": "toto", relationship : {OtherSchema...} }
FooSchema(only=["id", "relationship"]).dump() -> {"id": 1, relationship : {OtherSchema...} }
FooSchema(only=["id"]).dump() -> {"id": 1}
FooSchema(only=["default_excluded_field"]).dump() -> {"default_excluded_field": "test"}
FooSchema(only=["+default_excluded_field"]).dump() -> {"id": 1, "name": "toto", "default_excluded_field": "test"}
FooSchema(only=["relationship"]).dump() -> {"id": 1, "name": "toto", "relationship": {OtherSchema...} }
FooSchema(only=["id", "relationship"]).dump() -> {"id": 1, "relationship": {OtherSchema...}}
FooSchema(only=["-", "relationship"]).dump() -> {"relationship": {OtherSchema...}}
"""

def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -68,6 +76,7 @@ def __init__(self, *args, **kwargs):
# If only does not contains nested or additional fields, we do nothing and marshmallow will serialize only specified fields.
if only and not firstlevel_only - nested_fields - additional_fields:
only |= included_fields
only -= {"-"}
if only:
kwargs["only"] = only
if exclude:
Expand Down
11 changes: 11 additions & 0 deletions src/utils_flask_sqla/tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,17 @@ def test_null_relationship(self):
{"pk": 1, "col": None, "parent_pk": None, "parent": None, "address_pk": None},
)

def test_no_firstlevel_fields(self):
child = Child(pk=1)
parent = Parent(pk=1, childs=[child])

TestCase().assertDictEqual(
ParentSchema(only=("-", "childs.pk")).dump(parent),
{
"childs": [{"pk": 1}],
},
)

def test_polymorphic_model(self):
class PolyModel(db.Model):
__mapper_args__ = {
Expand Down

0 comments on commit bbf3d9d

Please sign in to comment.