Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add embed schema parameter and embed_only field option #1781

Closed
wants to merge 7 commits into from

Conversation

bpneumann
Copy link

Implements the functionality described in #151.
Similar to the functionality of only, but allows fields to be marked as embed_only. A common use case for this is for schemas which contain large collections which should only be serialized in specific cases.

Add support for embed_only option on fields, and as a Meta option in schema classes.

If a field is marked as embed_only, the field will only be serialized if it is included in embed schema parameter.

Example:

    class MySchema(Schema):
        foo = fields.Field(embed_only=True)

    sch = MySchema()
    assert "foo" not in sch.dump({"foo": "bar"})

    sch = MySchema(embed=['foo'])
    assert "foo" in sch.dump({"foo": "bar"})

This also supports nested fields using the same dotted identifiers used by the only option.

    class ChildSchema(Schema):
        bar = fields.Field(embed_only=True)
        baz = fields.Field(embed_only=True)

    class ParentSchema(Schema):
        foo = fields.Nested(ChildSchema())

    sch = ParentSchema(embed=['foo.bar'])
    dump = sch.dump({"foo": {"bar": "val", "baz": "val"}})
    assert "foo" in dump
    assert "bar" in dump["foo"]
    assert "baz" not in dump["foo"] 

@bpneumann bpneumann changed the title Add embed only Add embed schema parameter and embed_only field option Mar 31, 2021
@sloria
Copy link
Member

sloria commented Apr 4, 2021

I believe this is the same use case described in #244 . See the "include" recipe for a way to address it.

Holding off on this PR for now.

@sloria sloria closed this Apr 4, 2021
@bpneumann
Copy link
Author

This recipe works for schemas without nested fields, but offers no way to include fields on nested fields.

Extending the example from #1737 (comment)

class Organization(BaseSchema):
    members = fields.Nested(Member())
    name = fields.String()

organization = Model(name="Book Club", members=[member])

pprint(Organization(include=("members.photo",)).dump(organization))
# raises KeyError

Since members.photo is not a field on Organization, this raises a KeyError. The desired behavior would be to set include on the Organization schema to members, and propagate photo to the include parameter of the nested Member schema.

A full solution to this can currently only be accomplished by subclassing Schema as well as Nested to accommodate the include option, and overriding the initializers, _init_fields, and _normalize_nested_options.

Alternatively, this could be made simpler with the changes proposed in #1725 allowing subclasses of schema to update fields before serialization/deserialization according to extra arguments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants