Skip to content

Add ability to omit certain fields from a model when converting to a dict #228

Closed

Description

@emann

Is your feature request related to a problem? Please describe.
I have an endpoint which has optional fields in the body where optional means "can be excluded" instead of "can be null" (where these have different behavior e.g. null means set to null vs. not included means "don't change"). When using a generated client to hit the endpoint, optional fields that I don't set are sent up as None, causing the API to interpret it as "update this value to equal None" instead of "I'm not changing this value so leave it alone". It'd be nice to have a way to specify fields to include/exclude when making a model and/or when using it, ideally with options similar to pydantic's when exporting a schema to a dictionary

Describe the solution you'd like
At a minimum, I'd like to be able to specify the following in a model's .to_dict():

  • include - a set of field names to include in the dictionary
  • exclude - a set of field names to exclude from the dictionary (only one of this and include should be used at once)
  • exclude_unset - if True, values that aren't explicitly set are excluded. This one might be tricky as I don't think attrs classes keep track of what has or hasn't been set
  • exclude_none - a nice catch-all for excluding any value set to None.

Once these parameters are available in models' .to_dict() there would need to be a way to specify what params to use when calling a model's .to_dict() in an endpoint's _get_kwargs. I have two ideas for how this could be done:=

  • All model's inherit from a BaseModel that has an attribute called something like model_config or to_dict_config that can be set on a per-instance basis i.e. my_model.to_dict_config = {"exclude": {"owner_pk", "location_pk"}}
  • Implement the above params as methods on a BaseModel class (or per model but thats a tad yucky) to use them as a fluid API i.e. my_model = MyModel(**data).include({"thing1","thing2"}).exclude_none(True) etc.

Describe alternatives you've considered
An alternative would be to just convert all generated models to be pydantic schemas, thus allowing us to leverage the handy options in its .dict().

Activity

  1. emann commented on Oct 30, 2020

    @emann
    ContributorAuthor

    @dbanty Need your opinion on how you'd prefer to implement

  2. bowenwr commented on Oct 30, 2020

    @bowenwr
    Contributor

    Pretty much the same issue we had with #205, which I accidentally closed when I put a partial solution in our fork. 😬

    We went with defaulting properties to Unset when not required and then modified to_dict() not to send anything Unset.

  3. emann commented on Oct 30, 2020

    @emann
    ContributorAuthor

    @bowenwr I still think having these params on models' .to_dict() is useful regardless for use outside of _get_kwargs. The notion of UNSET removes the need for either of the options for determining what params to call .to_dict() with inside of _get_kwargs however, as .to_dict() would just be called with exclude_unset=True.

    I took a peek at your fork and I like the semantics of UNSET + it would definitely solve the issue I'm having - any chance you could make a PR for it? Once the UNSET logic is in I can start work on the above to bring it all together. If not I can steal some stuff from your fork and make a PR myself (giving you plenty of credit obviously) that includes both the UNSET stuff and the params for .to_dict().

  4. added this to the 0.7.0 milestone on Nov 4, 2020
  5. dbanty commented on Nov 6, 2020

    @dbanty
    Collaborator

    Closed by #230

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions