After looking through the source code, I don't see any way that this would be easily possible with the specialized kwarg supplied. The dict function is recursive and doesn't support arbitrary arguments.

Now, I was able to hack something together but... it is awful. This was performed using pydantic==1.10.7.

I was thinking we could apply a special flag value in the exclude arguments to provide something to trigger the exclusion logic off of. This became trickier than I expected, because it requires knowing the full structure of the object and exactly how to index the excluded fields. There is also some odd normalization happening on lists, which is causing the value provided to be mutated as it makes its way down the function call.

This is the best I could get (WARNING not tested thoroughly). We create a dictionary that returns itself on every lookup, that exposed __all__ as an exclude field. This will allow our key to be passed to each and every model, and be passed on to child objects to evaluate as well.

EXCLUDED_SPECIAL_FIELDS = "exclude_special_fields"

class _ExclusionDict(dict):
    def __init__(self):
        super().__init__({"__all__": {EXCLUDED_SPECIAL_FIELDS: True}})

    def get(self, key):
        return self


ExcludeSpecial = _ExclusionDict()


class SpecialExclusionBaseModel(BaseModel):
    _special_exclusions: set[str]

    def dict(self, **kwargs):
        exclusions = getattr(self.__class__, "_special_exclusions", None)
        exclude = kwargs.get("exclude")
        if exclusions and exclude and EXCLUDED_SPECIAL_FIELDS in exclude:
            return {
                k: v
                for k, v in super().dict(**kwargs).items()
                if k not in exclusions
            }
        return super().dict(**kwargs)

With this base class, we can provide a class field called _special_exclusions to indicate which fields we want excluded when the ExcludeSpecial instance is provided as the exclude kw argument.

On some initial testing, this seems to work with nested hierarchies including dicts and lists. There are probably bugs here that need to be worked out, but hopefully this is a good jumping off point for others.

class MyModel(SpecialExclusionBaseModel):
    _special_exclusions = {"field"}
    field: str

class AnotherModel(BaseModel):
    models: list[MyModel]

class AnotherAnotherModel(BaseModel):
    models: dict[str, AnotherModel]


model = MyModel(field=1)
another = AnotherAnotherModel(models={"test": AnotherModel(models=[model])})
print(another.dict(exclude=ExcludeSpecial))
{'models': {'test': {'models': [{}]}}}
Answer from flakes on Stack Overflow
🌐
GitHub
github.com › pydantic › pydantic › issues › 11099
Allow field exclusion for nested models AND/OR allow field additions for `model_dump` · Issue #11099 · pydantic/pydantic
December 12, 2024 - I would like to be able to define a field on a model that can be removed in all nested occurrences when calling model_dump at runtime (ie not using exclude on the Field definition) . See below example for an attempt that does NOT work: # Trying nested properties from typing import Optional from pydantic import BaseModel, Field, field_validator class BaseModel2(BaseModel): class_name: Optional[str] = Field(None, validate_default=True) @field_validator("class_name") @classmethod def set_class_name(cls, v): if v is None: return cls.__name__ else: raise ValueError("class_name must not be set") cla
Author   maxschulz-COL
Top answer
1 of 2
3

After looking through the source code, I don't see any way that this would be easily possible with the specialized kwarg supplied. The dict function is recursive and doesn't support arbitrary arguments.

Now, I was able to hack something together but... it is awful. This was performed using pydantic==1.10.7.

I was thinking we could apply a special flag value in the exclude arguments to provide something to trigger the exclusion logic off of. This became trickier than I expected, because it requires knowing the full structure of the object and exactly how to index the excluded fields. There is also some odd normalization happening on lists, which is causing the value provided to be mutated as it makes its way down the function call.

This is the best I could get (WARNING not tested thoroughly). We create a dictionary that returns itself on every lookup, that exposed __all__ as an exclude field. This will allow our key to be passed to each and every model, and be passed on to child objects to evaluate as well.

EXCLUDED_SPECIAL_FIELDS = "exclude_special_fields"

class _ExclusionDict(dict):
    def __init__(self):
        super().__init__({"__all__": {EXCLUDED_SPECIAL_FIELDS: True}})

    def get(self, key):
        return self


ExcludeSpecial = _ExclusionDict()


class SpecialExclusionBaseModel(BaseModel):
    _special_exclusions: set[str]

    def dict(self, **kwargs):
        exclusions = getattr(self.__class__, "_special_exclusions", None)
        exclude = kwargs.get("exclude")
        if exclusions and exclude and EXCLUDED_SPECIAL_FIELDS in exclude:
            return {
                k: v
                for k, v in super().dict(**kwargs).items()
                if k not in exclusions
            }
        return super().dict(**kwargs)

With this base class, we can provide a class field called _special_exclusions to indicate which fields we want excluded when the ExcludeSpecial instance is provided as the exclude kw argument.

On some initial testing, this seems to work with nested hierarchies including dicts and lists. There are probably bugs here that need to be worked out, but hopefully this is a good jumping off point for others.

class MyModel(SpecialExclusionBaseModel):
    _special_exclusions = {"field"}
    field: str

class AnotherModel(BaseModel):
    models: list[MyModel]

class AnotherAnotherModel(BaseModel):
    models: dict[str, AnotherModel]


model = MyModel(field=1)
another = AnotherAnotherModel(models={"test": AnotherModel(models=[model])})
print(another.dict(exclude=ExcludeSpecial))
{'models': {'test': {'models': [{}]}}}
2 of 2
2

You can use model_dump( {nested_modeL_name: {fields_to_exclude} } )

and for nested list of model model_dump(nested_model_name:{"\__all_\_": {fields_to_exclude}} )

ref: https://github.com/pydantic/pydantic/discussions/9382

Discussions

Recursively exclude all 'None' fields in a deeply nested Pydantic model?
No, mymodel.model_dump(exclude_none=True) works recursively. It is NOT a per-class option, much to my annoyance (but the new field-level exclude_if can be used for this). Docs: exclude_none: https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_dump available per-class settings, note the absence of exclude_none: https://docs.pydantic.dev/latest/api/config/ Personally, I think exclude_none is a bit of an antipattern, because the shape of the resulting data will violate the promised JSON schema (if that's relevant for you). Instead, use the exclude-defaults feature. More on reddit.com
🌐 r/learnpython
1
0
October 24, 2025
Nested exclude support
So I see a solution in adding new arg called nested_exclude or deep_exclude, keys in which will be excluded from all nested models and even dicts: from pydantic import BaseModel, SecretStr class User(BaseModel): id: int username: str password: SecretStr class Transaction(BaseModel): id: str ... More on github.com
🌐 github.com
16
July 5, 2019
python - pydantic exclude multiple fields from model - Stack Overflow
5 pydantic model: How to exclude field from being hashed / eq-compared? ... 15 How do I use FastAPI's "response_model_exclude_none=True" to exclude "None" values from nested models? More on stackoverflow.com
🌐 stackoverflow.com
Pydantic v2 exclude parameter in Field and Annotated
I think that it's because you annotated it as Optional[Annotated[User, Field(exclude=True)]]. That basically means either None or annotated User. Try this Annotated[Optional[User], Field(exclude=True)] Your typing is kind of weird, you say you want it to be either None or excluded. And I think pydantic cannot resolve it because it's not applied to all the possibilities in the field. If I should guess, pydantic doesn't even check for Annotated when it's not the root type as it doesn't make much sense. More on reddit.com
🌐 r/learnpython
5
1
January 1, 2024
🌐
Medium
medium.com › @balakrishnamaduru › efficiently-filtering-non-none-values-from-nested-pydantic-models-5b86256ab681
Efficiently Filtering Non-None Values from Nested Pydantic Models | by Balakrishna Maduru | Medium
February 7, 2025 - This model has a method get_non_none_values to exclude any fields that are None: from pydantic import BaseModel from typing import Optional class MyModel(BaseModel): name: Optional[str] = None age: Optional[int] = None email: Optional[str] = ...
🌐
GitHub
github.com › samuelcolvin › pydantic › issues › 640
Nested exclude support · Issue #640 · pydantic/pydantic
July 5, 2019 - So I see a solution in adding new arg called nested_exclude or deep_exclude, keys in which will be excluded from all nested models and even dicts: from pydantic import BaseModel, SecretStr class User(BaseModel): id: int username: str password: ...
Author   Bobronium
🌐
Reddit
reddit.com › r/learnpython › pydantic v2 exclude parameter in field and annotated
r/learnpython on Reddit: Pydantic v2 exclude parameter in Field and Annotated
January 1, 2024 -

I am playing around with Pydantic v2.5 and trying to see how the exclude works when set as a Field option. Let's imagine that I have a User BaseModel class and a Permissions BaseModel class. Both are used in the Config class.

We do not want to print the all User info, hence why I added the exclude in the Permissions class when the user is defined.

from typing import Annotated, Optional
from pydantic import BaseModel, Field


class User(BaseModel):
    name: str
    surname: str
    card_id: str


class Permissions(BaseModel):
    user: Annotated[User, Field(exclude=True)]
    config_rule: str


class Config:
    def __init__(self):
        self.user = User(**dict(name="Name", surname="Surname", card_id="12343545"))
        self.config_data = Permissions(user=self.user, config_rule="admin")

c = Config()
print(c.config_data.model_dump_json(indent=2))

In this case, the exclude set in the Permissions class seems to be working fine, in fact the print output is:

{
  "config_rule": "admin"
}

However, if I change the Permissions class with:

class Permissions(BaseModel):
    user: Optional[Annotated[User, Field(exclude=True)]]
    config_rule: str

The output is:

{
  "user": {
    "name": "Name",
    "surname": "Surname",
    "card_id": "12343545"
  },
  "config_rule": "admin"
}

And I am not sure I understand why. Any thoughts? Thanks.

Find elsewhere
🌐
GitHub
github.com › pydantic › pydantic › discussions › 6699
Remove an inherited field from a model in pydantic v2 · pydantic/pydantic · Discussion #6699
July 16, 2023 - This documentation not only includes how to exclude fields of nested fields, as well as fields which take the form of lists or tuples. ... from pydantic import BaseModel from typing import List class Credentials(BaseModel): username: str password: str class User(BaseModel): name: str credentials: Credentials user = User(name="charles", credentials=Credentials(username="charles123", password="super-secret-pw")) print(user.model_dump()) # > {'name': 'charles', 'credentials': {'username': 'charles123', 'password': 'super-secret-pw'}} print(user.model_dump(exclude={"credentials": {"password"}})) # > {'name': 'charles', 'credentials': {'username': 'charles123'}}
Author   pydantic
🌐
Pydantic
docs.pydantic.dev › 1.10 › usage › exporting_models
Exporting models - Pydantic
The dict, json, and copy methods support include and exclude arguments which can either be sets or dictionaries. This allows nested selection of which fields to export: ... from pydantic import BaseModel, SecretStr class User(BaseModel): id: int username: str password: SecretStr class ...
🌐
Pydantic
docs.pydantic.dev › latest › concepts › serialization
Serialization - Pydantic Validation
When using the serialization methods (such as model_dump()), several parameters can be used to exclude or include fields. ... from pydantic import BaseModel, Field, SecretStr class User(BaseModel): id: int username: str password: SecretStr class Transaction(BaseModel): id: str private_id: str = Field(exclude=True) user: User value: int t = Transaction( id='1234567890', private_id='123', user=User(id=42, username='JohnDoe', password='hashedpassword'), value=9876543210, )
🌐
Sentry
sentry.io › sentry answers › fastapi › exclude one or more fields in pydantic model from appearing in fastapi responses
Exclude one or more fields in Pydantic model from appearing in FastAPI responses | Sentry
from pydantic import BaseModel from datetime import datetime class User(BaseModel): username: str email: str address: str created_at: datetime · How do I keep these fields from appearing in responses while keeping them in the model? To exclude multiple fields from a Pydantic model, we can expand the type definition using Annotated from Python’s built-in typing module.
🌐
Reddit
reddit.com › r/fastapi › fetch an orm model and exclude nested field
r/FastAPI on Reddit: Fetch an orm model and exclude nested field
January 14, 2021 -

I have a list of items assigned to users that I want to fetch with a get request. Is there a way to retrieve this in a way that lists assigned_users as a list of usernames and ids instead of the full user model which also includes all the items created by the user and all the items assigned to them?

Pydantic Schema Models: User (id, username, items_created, items_assigned) Item: id, title, created_by, assigned_to

🌐
Bugbytes
bugbytes.io › posts › pydantic-field-function-and-model-config
Pydantic - Field function and Model Config - BugBytes
The special value __all__ allows us to exclude the nested field from all elements of the sequence. These are very useful features in Pydantic.
🌐
GitHub
github.com › samuelcolvin › pydantic › issues › 1283
Model export fails when excluding fields from a List of nested models · Issue #1283 · pydantic/pydantic
March 2, 2020 - from pydantic import BaseModel from typing import List class Foo(BaseModel): id: int class Bar(BaseModel): id: int foos: List[Foo] = [] my_bar = Bar(id=3) my_bar.dict() # This is ok my_bar.dict(exclude={"foos": {"id"}}) # This causes TypeError ... Traceback (most recent call last): File "tester.py", line 13, in <module> my_bar.dict(exclude={"foos": {"id"}}) File "/Users/misha/workflow/balsam/env/lib/python3.7/site-packages/pydantic/main.py", line 343, in dict exclude_none=exclude_none, File "/Users/misha/workflow/balsam/env/lib/python3.7/site-packages/pydantic/main.py", line 333, in <dictcomp>
Author   masalim2
🌐
Stack Overflow
stackoverflow.com › questions › 68968600 › exclude-fields-of-nested-objects-from-m2m-relation-when-creating-pydantic-model
python - Exclude fields of nested objects from m2m relation when creating pydantic model using pydantic_model_creator? - Stack Overflow
August 28, 2021 - What I want to achieve: I want to create a PydanticModel for Recipe that won't contain Ingredient.not_needed field, like so: pydantic_model_creator(Recipe, exclude=("ingredients.not_needed"))
Top answer
1 of 2
25

You could exclude only optional model fields that unset by making of union of model fields that are set and those that are not None.

Pydantic provides the following arguments for exporting method model.dict(...):

exclude_unset: whether fields which were not explicitly set when creating the model should be excluded from the returned dictionary; default False.

exclude_none: whether fields which are equal to None should be excluded from the returned dictionary; default False

To make union of two dicts we can use the expression a = {**b, **c} (values from c overwrites values from b). Note that since Python 3.9 it could be done just as a = b | c.

from pydantic import BaseModel
from typing import Optional
from pydantic.json import pydantic_encoder
import json


class Foo(BaseModel):
    x: int
    y: int = 42
    z: Optional[int]

def exclude_optional_dict(model: BaseModel):
    return {**model.dict(exclude_unset=True), **model.dict(exclude_none=True)}

def exclude_optional_json(model: BaseModel):
    return json.dumps(exclude_optional_dict(model), default=pydantic_encoder)
    


print(exclude_optional_json(Foo(x=3)))  # {"x": 3, "y": 42}
print(exclude_optional_json(Foo(x=3, z=None)))  # {"x": 3, "z": null, "y": 42}
print(exclude_optional_json(Foo(x=3, z=77)))  # {"x": 3, "z": 77, "y": 42}

Update

In order for the approach to work with nested models, we need to do a deep union( or merge) of two dictionaries, like so:

def union(source, destination):
    for key, value in source.items():
        if isinstance(value, dict):
            node = destination.setdefault(key, {})
            union(value, node)
        else:
            destination[key] = value

    return destination

def exclude_optional_dict(model: BaseModel):
    return union(model.dict(exclude_unset=True), model.dict(exclude_none=True))

class Foo(BaseModel):
    x: int
    y: int = 42
    z: Optional[int]

class Bar(BaseModel):
    a: int
    b: int = 52
    c: Optional[int]
    d: Foo


print(exclude_optional_json(Bar(a=4, d=Foo(x=3))))
print(exclude_optional_json(Bar(a=4, c=None, d=Foo(x=3, z=None))))
print(exclude_optional_json(Bar(a=4, c=78, d=Foo(x=3, z=77))))
{"a": 4, "b": 52, "d": {"x": 3, "y": 42}}
{"a": 4, "b": 52, "d": {"x": 3, "y": 42, "z": null}, "c": null}
{"a": 4, "b": 52, "c": 78, "d": {"x": 3, "y": 42, "z": 77}}
2 of 2
6

If you're using FastAPI then using exclude_none doesn't seem to work when a response_model is mentioned in the route decorator.

@app.post("/items/", response_model=Item)
async def create_item(item: Item):
    return item.dict(exclude_none=True)

Fast api seems to reprocess the dict with the pydantic model

So overriding the dict method in the model itself should work

def Item(BaseModel):
   name: str
   description: Optional[str]
   ...
   def dict(self, *args, **kwargs) -> Dict[str, Any]:
        kwargs.pop('exclude_none', None)
        return super().dict(*args, exclude_none=True, **kwargs)

(an actual solution would put this definition in separate subclass of BaseModel for reuse)

Note: just changing the default value of the exclude_none keyword argument is not enough: it seems FastAPI always sends exclude_none=False as an argument.


Source:
https://github.com/tiangolo/fastapi/issues/3314#issuecomment-962932368

🌐
GitHub
github.com › pydantic › pydantic › discussions › 8251
Is there a way to have extra fields excluded during model_dump? · pydantic/pydantic · Discussion #8251
December 1, 2023 - from pydantic import BaseModel, ConfigDict class Nested(BaseModel): model_config = ConfigDict(extra="allow") baz: str class Root(BaseModel): foo: int = 10 bar: int nested: Nested def remove_extras(model: BaseModel, data: dict) -> dict: """Recursively removes extra keys from the dumped version of a Model""" if model.model_extra: for key in model.model_extra.keys(): data.pop(key, None) for fieldname, field_info in model.model_fields.items(): value = getattr(model, fieldname) if hasattr(value, "model_extra"): data[fieldname] = remove_extras(value, data[fieldname]) return data if __name__ == "__main__": model = Root( foo=10, bar=20, nested={"baz": "boing", "extra": "so special"}, ) dumped_data = model.model_dump() dumped_data = remove_extras(model, dumped_data) assert "extra" not in dumped_data["nested"]
Author   pydantic
🌐
GitHub
github.com › pydantic › pydantic › discussions › 11091
Remove field from all nested models · pydantic/pydantic · Discussion #11091
What I would expect is that exclude allows me to exclude all class_name occurences, so far I haven't managed. If the above is not possible, then maybe something else is. My ultimate aim is to allow a context specific model dump. But crucially I do not want to change serialisation of a single field, I want to add some information (the class name of the model cls.__name__) to the model serialisation.
Author   pydantic