[{"data":1,"prerenderedAt":1983},["ShallowReactive",2],{"nav":3,"page-\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fexcluding-fields-per-endpoint\u002F":580,"surround-\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fexcluding-fields-per-endpoint\u002F":1982},[4,186,386],{"title":5,"path":6,"stem":7,"children":8},"Advanced Pydantic Validation Serialization","\u002Fadvanced-pydantic-validation-serialization","advanced-pydantic-validation-serialization",[9,12,42,66,90,114,150,174],{"title":10,"path":6,"stem":11},"Advanced Pydantic Validation and Serialization","advanced-pydantic-validation-serialization\u002Findex",{"title":13,"path":14,"stem":15,"children":16},"Custom Validators and Field Constraints in Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Findex",[17,18,24,30,36],{"title":13,"path":14,"stem":15},{"title":19,"path":20,"stem":21,"children":22},"Before, After and Wrap Validators in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fbefore-after-and-wrap-validators","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fbefore-after-and-wrap-validators\u002Findex",[23],{"title":19,"path":20,"stem":21},{"title":25,"path":26,"stem":27,"children":28},"Creating Reusable Custom Validators in Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcreating-reusable-custom-validators-in-pydantic","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcreating-reusable-custom-validators-in-pydantic\u002Findex",[29],{"title":25,"path":26,"stem":27},{"title":31,"path":32,"stem":33,"children":34},"Cross-Field Validation Patterns in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcross-field-validation-patterns","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcross-field-validation-patterns\u002Findex",[35],{"title":31,"path":32,"stem":33},{"title":37,"path":38,"stem":39,"children":40},"Pydantic v2 Async Custom Validator: What to Do Instead","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fpydantic-v2-async-custom-validator","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fpydantic-v2-async-custom-validator\u002Findex",[41],{"title":37,"path":38,"stem":39},{"title":43,"path":44,"stem":45,"children":46},"JSON Schema Customization in Pydantic and FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Findex",[47,48,54,60],{"title":43,"path":44,"stem":45},{"title":49,"path":50,"stem":51,"children":52},"Customizing OpenAPI Schema Generation in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fcustomizing-openapi-schema-generation-in-fastapi","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fcustomizing-openapi-schema-generation-in-fastapi\u002Findex",[53],{"title":49,"path":50,"stem":51},{"title":55,"path":56,"stem":57,"children":58},"Discriminated Unions in OpenAPI with Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fdiscriminated-unions-in-openapi","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fdiscriminated-unions-in-openapi\u002Findex",[59],{"title":55,"path":56,"stem":57},{"title":61,"path":62,"stem":63,"children":64},"Examples in the OpenAPI Schema with FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fexamples-in-openapi-schema","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fexamples-in-openapi-schema\u002Findex",[65],{"title":61,"path":62,"stem":63},{"title":67,"path":68,"stem":69,"children":70},"Nested Model Serialization in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Findex",[71,72,78,84],{"title":67,"path":68,"stem":69},{"title":73,"path":74,"stem":75,"children":76},"Excluding Fields Per Endpoint in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fexcluding-fields-per-endpoint","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fexcluding-fields-per-endpoint\u002Findex",[77],{"title":73,"path":74,"stem":75},{"title":79,"path":80,"stem":81,"children":82},"Handling Deeply Nested JSON Models Efficiently","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fhandling-deeply-nested-json-models-efficiently","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fhandling-deeply-nested-json-models-efficiently\u002Findex",[83],{"title":79,"path":80,"stem":81},{"title":85,"path":86,"stem":87,"children":88},"Self-Referencing and Recursive Models in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fself-referencing-and-recursive-models","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fself-referencing-and-recursive-models\u002Findex",[89],{"title":85,"path":86,"stem":87},{"title":91,"path":92,"stem":93,"children":94},"Performance Optimization for Pydantic Models in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Findex",[95,96,102,108],{"title":91,"path":92,"stem":93},{"title":97,"path":98,"stem":99,"children":100},"model_construct and When to Skip Validation in Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fmodel-construct-when-to-skip-validation","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fmodel-construct-when-to-skip-validation\u002Findex",[101],{"title":97,"path":98,"stem":99},{"title":103,"path":104,"stem":105,"children":106},"Pydantic Model Serialization Performance in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance\u002Findex",[107],{"title":103,"path":104,"stem":105},{"title":109,"path":110,"stem":111,"children":112},"TypeAdapter for Non-Model Types in Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Ftypeadapter-for-non-model-types","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Ftypeadapter-for-non-model-types\u002Findex",[113],{"title":109,"path":110,"stem":111},{"title":115,"path":116,"stem":117,"children":118},"Pydantic V2 Migration Guide for FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Findex",[119,120,126,132,138,144],{"title":115,"path":116,"stem":117},{"title":121,"path":122,"stem":123,"children":124},"Migrate @validator to @field_validator in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrate-validator-to-field-validator","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrate-validator-to-field-validator\u002Findex",[125],{"title":121,"path":122,"stem":123},{"title":127,"path":128,"stem":129,"children":130},"Migrating from Pydantic v1 to v2 Without Breaking APIs","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrating-from-pydantic-v1-to-v2-without-breaking-apis","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrating-from-pydantic-v1-to-v2-without-breaking-apis\u002Findex",[131],{"title":127,"path":128,"stem":129},{"title":133,"path":134,"stem":135,"children":136},"model_config vs class Config in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmodel-config-vs-class-config","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmodel-config-vs-class-config\u002Findex",[137],{"title":133,"path":134,"stem":135},{"title":139,"path":140,"stem":141,"children":142},"Replacing json_encoders with field_serializer in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Freplacing-json-encoders-with-field-serializer","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Freplacing-json-encoders-with-field-serializer\u002Findex",[143],{"title":139,"path":140,"stem":141},{"title":145,"path":146,"stem":147,"children":148},"Migrating @root_validator to @model_validator in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Froot-validator-to-model-validator","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Froot-validator-to-model-validator\u002Findex",[149],{"title":145,"path":146,"stem":147},{"title":151,"path":152,"stem":153,"children":154},"Request Validation Patterns in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Frequest-validation-patterns","advanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Findex",[155,156,162,168],{"title":151,"path":152,"stem":153},{"title":157,"path":158,"stem":159,"children":160},"Optional vs Nullable Fields in Pydantic and FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Foptional-vs-nullable-fields","advanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Foptional-vs-nullable-fields\u002Findex",[161],{"title":157,"path":158,"stem":159},{"title":163,"path":164,"stem":165,"children":166},"Query, Path and Body Parameter Validation in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Fquery-path-and-body-parameter-validation","advanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Fquery-path-and-body-parameter-validation\u002Findex",[167],{"title":163,"path":164,"stem":165},{"title":169,"path":170,"stem":171,"children":172},"Validating File Uploads and Forms in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Fvalidating-file-uploads-and-forms","advanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Fvalidating-file-uploads-and-forms\u002Findex",[173],{"title":169,"path":170,"stem":171},{"title":175,"path":176,"stem":177,"children":178},"Type Hinting and IDE Integration in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration","advanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration\u002Findex",[179,180],{"title":175,"path":176,"stem":177},{"title":181,"path":182,"stem":183,"children":184},"Annotated Dependencies and Reusable Types in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration\u002Fannotated-dependencies-and-reusable-types","advanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration\u002Fannotated-dependencies-and-reusable-types\u002Findex",[185],{"title":181,"path":182,"stem":183},{"title":187,"path":188,"stem":189,"children":190},"Async Background Tasks Observability","\u002Fasync-background-tasks-observability","async-background-tasks-observability",[191,194,224,254,284,308,338,362],{"title":192,"path":188,"stem":193},"Async, Background Tasks, and Observability in FastAPI","async-background-tasks-observability\u002Findex",{"title":195,"path":196,"stem":197,"children":198},"Async Correctness and Concurrency in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Findex",[199,200,206,212,218],{"title":195,"path":196,"stem":197},{"title":201,"path":202,"stem":203,"children":204},"Concurrent Requests with asyncio.gather in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency\u002Fconcurrent-requests-with-asyncio-gather","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Fconcurrent-requests-with-asyncio-gather\u002Findex",[205],{"title":201,"path":202,"stem":203},{"title":207,"path":208,"stem":209,"children":210},"FastAPI async def vs def: Performance and When to Use Each","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency\u002Ffastapi-async-def-vs-def-performance","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Ffastapi-async-def-vs-def-performance\u002Findex",[211],{"title":207,"path":208,"stem":209},{"title":213,"path":214,"stem":215,"children":216},"Fixing Blocking Calls in Async FastAPI Routes","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency\u002Ffixing-blocking-calls-in-async-routes","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Ffixing-blocking-calls-in-async-routes\u002Findex",[217],{"title":213,"path":214,"stem":215},{"title":219,"path":220,"stem":221,"children":222},"Running Sync Code in a Threadpool in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency\u002Frunning-sync-code-in-a-threadpool","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Frunning-sync-code-in-a-threadpool\u002Findex",[223],{"title":219,"path":220,"stem":221},{"title":225,"path":226,"stem":227,"children":228},"Async Database Sessions in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions","async-background-tasks-observability\u002Fasync-database-sessions\u002Findex",[229,230,236,242,248],{"title":225,"path":226,"stem":227},{"title":231,"path":232,"stem":233,"children":234},"Async SQLAlchemy Session per Request in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Fasync-sqlalchemy-session-per-request","async-background-tasks-observability\u002Fasync-database-sessions\u002Fasync-sqlalchemy-session-per-request\u002Findex",[235],{"title":231,"path":232,"stem":233},{"title":237,"path":238,"stem":239,"children":240},"Fixing asyncpg Connection Pool Exhaustion in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Ffixing-asyncpg-pool-exhaustion","async-background-tasks-observability\u002Fasync-database-sessions\u002Ffixing-asyncpg-pool-exhaustion\u002Findex",[241],{"title":237,"path":238,"stem":239},{"title":243,"path":244,"stem":245,"children":246},"Testing with Async Database Fixtures in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Ftesting-with-async-database-fixtures","async-background-tasks-observability\u002Fasync-database-sessions\u002Ftesting-with-async-database-fixtures\u002Findex",[247],{"title":243,"path":244,"stem":245},{"title":249,"path":250,"stem":251,"children":252},"Transaction Management and Rollback in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Ftransaction-management-and-rollback","async-background-tasks-observability\u002Fasync-database-sessions\u002Ftransaction-management-and-rollback\u002Findex",[253],{"title":249,"path":250,"stem":251},{"title":255,"path":256,"stem":257,"children":258},"Background Task Processing in FastAPI","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing","async-background-tasks-observability\u002Fbackground-task-processing\u002Findex",[259,260,266,272,278],{"title":255,"path":256,"stem":257},{"title":261,"path":262,"stem":263,"children":264},"FastAPI BackgroundTasks vs Celery vs ARQ","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing\u002Ffastapi-backgroundtasks-vs-celery-vs-arq","async-background-tasks-observability\u002Fbackground-task-processing\u002Ffastapi-backgroundtasks-vs-celery-vs-arq\u002Findex",[265],{"title":261,"path":262,"stem":263},{"title":267,"path":268,"stem":269,"children":270},"Retry and Idempotency for FastAPI Background Tasks","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing\u002Fretry-and-idempotency-for-tasks","async-background-tasks-observability\u002Fbackground-task-processing\u002Fretry-and-idempotency-for-tasks\u002Findex",[271],{"title":267,"path":268,"stem":269},{"title":273,"path":274,"stem":275,"children":276},"Running ARQ Workers with FastAPI","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing\u002Frunning-arq-workers-with-fastapi","async-background-tasks-observability\u002Fbackground-task-processing\u002Frunning-arq-workers-with-fastapi\u002Findex",[277],{"title":273,"path":274,"stem":275},{"title":279,"path":280,"stem":281,"children":282},"When FastAPI BackgroundTasks Silently Fails","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing\u002Fwhen-backgroundtasks-silently-fails","async-background-tasks-observability\u002Fbackground-task-processing\u002Fwhen-backgroundtasks-silently-fails\u002Findex",[283],{"title":279,"path":280,"stem":281},{"title":285,"path":286,"stem":287,"children":288},"Caching Strategies in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies","async-background-tasks-observability\u002Fcaching-strategies\u002Findex",[289,290,296,302],{"title":285,"path":286,"stem":287},{"title":291,"path":292,"stem":293,"children":294},"Cache Invalidation Patterns in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies\u002Fcache-invalidation-patterns-in-fastapi","async-background-tasks-observability\u002Fcaching-strategies\u002Fcache-invalidation-patterns-in-fastapi\u002Findex",[295],{"title":291,"path":292,"stem":293},{"title":297,"path":298,"stem":299,"children":300},"Caching Dependency Results in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies\u002Fcaching-dependency-results","async-background-tasks-observability\u002Fcaching-strategies\u002Fcaching-dependency-results\u002Findex",[301],{"title":297,"path":298,"stem":299},{"title":303,"path":304,"stem":305,"children":306},"Redis Response Caching in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies\u002Fredis-response-caching-in-fastapi","async-background-tasks-observability\u002Fcaching-strategies\u002Fredis-response-caching-in-fastapi\u002Findex",[307],{"title":303,"path":304,"stem":305},{"title":309,"path":310,"stem":311,"children":312},"Observability and Tracing in FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing","async-background-tasks-observability\u002Fobservability-and-tracing\u002Findex",[313,314,320,326,332],{"title":309,"path":310,"stem":311},{"title":315,"path":316,"stem":317,"children":318},"Correlating Logs, Traces and Errors in FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing\u002Fcorrelating-logs-traces-and-errors","async-background-tasks-observability\u002Fobservability-and-tracing\u002Fcorrelating-logs-traces-and-errors\u002Findex",[319],{"title":315,"path":316,"stem":317},{"title":321,"path":322,"stem":323,"children":324},"Instrumenting FastAPI with OpenTelemetry","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing\u002Finstrumenting-fastapi-with-opentelemetry","async-background-tasks-observability\u002Fobservability-and-tracing\u002Finstrumenting-fastapi-with-opentelemetry\u002Findex",[325],{"title":321,"path":322,"stem":323},{"title":327,"path":328,"stem":329,"children":330},"Prometheus Metrics for FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing\u002Fprometheus-metrics-for-fastapi","async-background-tasks-observability\u002Fobservability-and-tracing\u002Fprometheus-metrics-for-fastapi\u002Findex",[331],{"title":327,"path":328,"stem":329},{"title":333,"path":334,"stem":335,"children":336},"Structured JSON Logging with Request IDs in FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing\u002Fstructured-json-logging-with-request-ids","async-background-tasks-observability\u002Fobservability-and-tracing\u002Fstructured-json-logging-with-request-ids\u002Findex",[337],{"title":333,"path":334,"stem":335},{"title":339,"path":340,"stem":341,"children":342},"Rate Limiting and Throttling in FastAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling","async-background-tasks-observability\u002Frate-limiting-throttling\u002Findex",[343,344,350,356],{"title":339,"path":340,"stem":341},{"title":345,"path":346,"stem":347,"children":348},"FastAPI Rate Limiting with Redis and SlowAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling\u002Ffastapi-rate-limiting-with-redis-slowapi","async-background-tasks-observability\u002Frate-limiting-throttling\u002Ffastapi-rate-limiting-with-redis-slowapi\u002Findex",[349],{"title":345,"path":346,"stem":347},{"title":351,"path":352,"stem":353,"children":354},"Per-User Token Bucket Throttling in FastAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling\u002Fper-user-token-bucket-throttling","async-background-tasks-observability\u002Frate-limiting-throttling\u002Fper-user-token-bucket-throttling\u002Findex",[355],{"title":351,"path":352,"stem":353},{"title":357,"path":358,"stem":359,"children":360},"Rate Limit Headers and 429 Responses in FastAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling\u002Frate-limit-headers-and-429-responses","async-background-tasks-observability\u002Frate-limiting-throttling\u002Frate-limit-headers-and-429-responses\u002Findex",[361],{"title":357,"path":358,"stem":359},{"title":363,"path":364,"stem":365,"children":366},"Testing FastAPI Applications","\u002Fasync-background-tasks-observability\u002Ftesting-fastapi-applications","async-background-tasks-observability\u002Ftesting-fastapi-applications\u002Findex",[367,368,374,380],{"title":363,"path":364,"stem":365},{"title":369,"path":370,"stem":371,"children":372},"Mocking External Services in FastAPI Tests","\u002Fasync-background-tasks-observability\u002Ftesting-fastapi-applications\u002Fmocking-external-services-in-tests","async-background-tasks-observability\u002Ftesting-fastapi-applications\u002Fmocking-external-services-in-tests\u002Findex",[373],{"title":369,"path":370,"stem":371},{"title":375,"path":376,"stem":377,"children":378},"TestClient vs httpx AsyncClient in FastAPI","\u002Fasync-background-tasks-observability\u002Ftesting-fastapi-applications\u002Ftestclient-vs-httpx-asyncclient","async-background-tasks-observability\u002Ftesting-fastapi-applications\u002Ftestclient-vs-httpx-asyncclient\u002Findex",[379],{"title":375,"path":376,"stem":377},{"title":381,"path":382,"stem":383,"children":384},"Testing Async FastAPI Endpoints with pytest-asyncio","\u002Fasync-background-tasks-observability\u002Ftesting-fastapi-applications\u002Ftesting-async-endpoints-with-pytest-asyncio","async-background-tasks-observability\u002Ftesting-fastapi-applications\u002Ftesting-async-endpoints-with-pytest-asyncio\u002Findex",[385],{"title":381,"path":382,"stem":383},{"title":387,"path":388,"stem":389,"children":390},"Core Architecture Routing Patterns","\u002Fcore-architecture-routing-patterns","core-architecture-routing-patterns",[391,394,412,436,472,496,526,556],{"title":392,"path":388,"stem":393},"FastAPI Core Architecture and Routing Patterns","core-architecture-routing-patterns\u002Findex",{"title":395,"path":396,"stem":397,"children":398},"Application Factory Patterns in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Findex",[399,400,406],{"title":395,"path":396,"stem":397},{"title":401,"path":402,"stem":403,"children":404},"FastAPI App Factory Pattern for Testing and Deployment","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Ffastapi-app-factory-pattern-for-testing-and-deployment","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Ffastapi-app-factory-pattern-for-testing-and-deployment\u002Findex",[405],{"title":401,"path":402,"stem":403},{"title":407,"path":408,"stem":409,"children":410},"Lifespan Events vs Startup and Shutdown in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Flifespan-events-vs-startup-shutdown","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Flifespan-events-vs-startup-shutdown\u002Findex",[411],{"title":407,"path":408,"stem":409},{"title":413,"path":414,"stem":415,"children":416},"Configuration Management in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management","core-architecture-routing-patterns\u002Fconfiguration-management\u002Findex",[417,418,424,430],{"title":413,"path":414,"stem":415},{"title":419,"path":420,"stem":421,"children":422},"Managing Environment Variables with Pydantic Settings","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management\u002Fmanaging-environment-variables-with-pydantic-settings","core-architecture-routing-patterns\u002Fconfiguration-management\u002Fmanaging-environment-variables-with-pydantic-settings\u002Findex",[423],{"title":419,"path":420,"stem":421},{"title":425,"path":426,"stem":427,"children":428},"Pydantic Settings vs Dynaconf vs python-decouple","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management\u002Fpydantic-settings-vs-dynaconf-vs-python-decouple","core-architecture-routing-patterns\u002Fconfiguration-management\u002Fpydantic-settings-vs-dynaconf-vs-python-decouple\u002Findex",[429],{"title":425,"path":426,"stem":427},{"title":431,"path":432,"stem":433,"children":434},"Secrets and .env Files Per Environment in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management\u002Fsecrets-and-env-files-per-environment","core-architecture-routing-patterns\u002Fconfiguration-management\u002Fsecrets-and-env-files-per-environment\u002Findex",[435],{"title":431,"path":432,"stem":433},{"title":437,"path":438,"stem":439,"children":440},"Dependency Injection Strategies in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Findex",[441,442,448,454,460,466],{"title":437,"path":438,"stem":439},{"title":443,"path":444,"stem":445,"children":446},"Best Practices for FastAPI Dependency Injection","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fbest-practices-for-fastapi-dependency-injection","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fbest-practices-for-fastapi-dependency-injection\u002Findex",[447],{"title":443,"path":444,"stem":445},{"title":449,"path":450,"stem":451,"children":452},"Dependency Caching and use_cache in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fdependency-caching-and-use-cache","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fdependency-caching-and-use-cache\u002Findex",[453],{"title":449,"path":450,"stem":451},{"title":455,"path":456,"stem":457,"children":458},"Fixing FastAPI Dependency Injection Circular Imports","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Ffastapi-dependency-injection-circular-import-fix","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Ffastapi-dependency-injection-circular-import-fix\u002Findex",[459],{"title":455,"path":456,"stem":457},{"title":461,"path":462,"stem":463,"children":464},"Overriding Dependencies in FastAPI Tests","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Foverriding-dependencies-in-tests","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Foverriding-dependencies-in-tests\u002Findex",[465],{"title":461,"path":462,"stem":463},{"title":467,"path":468,"stem":469,"children":470},"Yield Dependencies and Cleanup Order in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fyield-dependencies-and-cleanup-order","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fyield-dependencies-and-cleanup-order\u002Findex",[471],{"title":467,"path":468,"stem":469},{"title":473,"path":474,"stem":475,"children":476},"Error Handling and Global Exceptions in FastAPI","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Findex",[477,478,484,490],{"title":473,"path":474,"stem":475},{"title":479,"path":480,"stem":481,"children":482},"Customising Validation Error Responses in FastAPI","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fcustomising-validation-error-responses","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fcustomising-validation-error-responses\u002Findex",[483],{"title":479,"path":480,"stem":481},{"title":485,"path":486,"stem":487,"children":488},"Global Exception Handlers for Consistent API Responses","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fglobal-exception-handlers-for-consistent-api-responses","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fglobal-exception-handlers-for-consistent-api-responses\u002Findex",[489],{"title":485,"path":486,"stem":487},{"title":491,"path":492,"stem":493,"children":494},"HTTPException vs Custom Exception Classes in FastAPI","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fhttpexception-vs-custom-exception-classes","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fhttpexception-vs-custom-exception-classes\u002Findex",[495],{"title":491,"path":492,"stem":493},{"title":497,"path":498,"stem":499,"children":500},"Middleware Implementation in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Findex",[501,502,508,514,520],{"title":497,"path":498,"stem":499},{"title":503,"path":504,"stem":505,"children":506},"CORS Middleware Configuration in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fcors-middleware-configuration","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fcors-middleware-configuration\u002Findex",[507],{"title":503,"path":504,"stem":505},{"title":509,"path":510,"stem":511,"children":512},"Implementing Custom Middleware for Request Tracing","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fimplementing-custom-middleware-for-request-tracing","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fimplementing-custom-middleware-for-request-tracing\u002Findex",[513],{"title":509,"path":510,"stem":511},{"title":515,"path":516,"stem":517,"children":518},"Middleware Execution Order in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fmiddleware-execution-order","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fmiddleware-execution-order\u002Findex",[519],{"title":515,"path":516,"stem":517},{"title":521,"path":522,"stem":523,"children":524},"Middleware vs Dependencies: When to Use Which","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fmiddleware-vs-dependencies-when-to-use-which","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fmiddleware-vs-dependencies-when-to-use-which\u002Findex",[525],{"title":521,"path":522,"stem":523},{"title":527,"path":528,"stem":529,"children":530},"Modular Router Organization in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Findex",[531,532,538,544,550],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"APIRouter Prefix vs Sub-Application Mounting in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Fapirouter-prefix-vs-sub-application-mounting","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Fapirouter-prefix-vs-sub-application-mounting\u002Findex",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541,"children":542},"How to Structure Large FastAPI Projects for Scale","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Fhow-to-structure-large-fastapi-projects-for-scale","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Fhow-to-structure-large-fastapi-projects-for-scale\u002Findex",[543],{"title":539,"path":540,"stem":541},{"title":545,"path":546,"stem":547,"children":548},"Router Tags and OpenAPI Grouping in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Frouter-tags-and-openapi-grouping","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Frouter-tags-and-openapi-grouping\u002Findex",[549],{"title":545,"path":546,"stem":547},{"title":551,"path":552,"stem":553,"children":554},"Versioning APIs with FastAPI Routers","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Fversioning-apis-with-routers","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Fversioning-apis-with-routers\u002Findex",[555],{"title":551,"path":552,"stem":553},{"title":557,"path":558,"stem":559,"children":560},"The FastAPI Request\u002FResponse Lifecycle","\u002Fcore-architecture-routing-patterns\u002Frequest-response-lifecycle","core-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Findex",[561,562,568,574],{"title":557,"path":558,"stem":559},{"title":563,"path":564,"stem":565,"children":566},"How a Request Flows Through FastAPI","\u002Fcore-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fhow-a-request-flows-through-fastapi","core-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fhow-a-request-flows-through-fastapi\u002Findex",[567],{"title":563,"path":564,"stem":565},{"title":569,"path":570,"stem":571,"children":572},"Response Model and Serialization Order","\u002Fcore-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fresponse-model-and-serialization-order","core-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fresponse-model-and-serialization-order\u002Findex",[573],{"title":569,"path":570,"stem":571},{"title":575,"path":576,"stem":577,"children":578},"Streaming and File Responses in FastAPI","\u002Fcore-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fstreaming-and-file-responses","core-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fstreaming-and-file-responses\u002Findex",[579],{"title":575,"path":576,"stem":577},{"id":581,"title":73,"body":582,"dateModified":1951,"datePublished":1951,"description":1952,"extension":1953,"faq":1954,"howto":1965,"meta":1966,"navigation":962,"path":74,"seo":1979,"stem":75,"type":1980,"__hash__":1981},"content\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fexcluding-fields-per-endpoint\u002Findex.md",{"type":583,"value":584,"toc":1929},"minimark",[585,589,596,649,658,663,670,677,681,691,702,708,719,844,848,859,863,873,1211,1229,1233,1240,1246,1252,1311,1317,1326,1330,1337,1417,1423,1430,1437,1448,1454,1484,1490,1497,1503,1509,1532,1538,1541,1547,1557,1561,1573,1579,1610,1620,1627,1631,1692,1696,1699,1822,1828,1832,1839,1842,1845,1849,1860,1866,1875,1884,1890,1894,1925],[586,587,73],"h1",{"id":588},"excluding-fields-per-endpoint-in-fastapi",[590,591,592],"p",{},[593,594,595],"strong",{},"Key takeaways:",[597,598,599,611,621,630,637],"ul",{},[600,601,602,606,607,610],"li",{},[603,604,605],"code",{},"response_model_exclude"," drops named fields; ",[603,608,609],{},"response_model_include"," is its allow-list twin.",[600,612,613,616,617,620],{},[603,614,615],{},"response_model_exclude_unset"," drops anything never explicitly set — defaults vanish, including ",[603,618,619],{},"None"," defaults.",[600,622,623,626,627,629],{},[603,624,625],{},"response_model_exclude_none"," drops anything whose value is ",[603,628,619],{},", whether set or not.",[600,631,632,633,636],{},"Nested exclusion uses a dict: ",[603,634,635],{},"{\"password_hash\": True, \"address\": {\"internal_geocode\"}}",".",[600,638,639,640,644,645,648],{},"Exclusion filters the ",[641,642,643],"em",{},"output",": an excluded ",[603,646,647],{},"computed_field"," is skipped, but an excluded ordinary field was already fetched and validated — measured below.",[590,650,651,652,657],{},"This page is part of ",[653,654,656],"a",{"href":655},"\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002F","nested model serialization",", where the same options apply through arbitrarily deep structures.",[659,660,662],"h2",{"id":661},"the-problem-this-solves","The Problem This Solves",[590,664,665,666,669],{},"One ",[603,667,668],{},"User"," model is used by five endpoints. The admin listing should show everything, the public profile must not show the password hash, the \"changes since last sync\" endpoint should send only the fields that were actually set, and the mobile client wants nulls omitted to save bandwidth. Defining five near-identical response models is a maintenance cost nobody wants.",[590,671,672,673,676],{},"FastAPI's per-route serialization parameters solve this without new classes — and they come with a trap that costs people real incidents, which is a widespread confusion about ",[641,674,675],{},"when"," exclusion happens and therefore what it protects you from.",[659,678,680],{"id":679},"why-it-happens","Why It Happens",[590,682,683,684,687,688,636],{},"When a path operation declares ",[603,685,686],{},"response_model",", FastAPI does two things after your function returns. First it reconciles the returned object with that model. Then it serializes, passing the route's exclusion parameters straight through to ",[603,689,690],{},"model_dump",[590,692,693,694,697,698,701],{},"Exclusion is therefore a parameter to the ",[641,695,696],{},"last"," step. Everything upstream of it has already happened: the row was selected, the column was read, the value was validated into a field, and it has been sitting in memory for the whole request. Dropping ",[603,699,700],{},"password_hash"," at serialization time does not mean the hash was never handled — it means the hash was handled and then not printed.",[590,703,704,705,707],{},"Inside that last step, Pydantic is smarter than people assume. The selection is resolved before the serializer walks the fields, so a ",[603,706,647],{}," that the selection excludes is never evaluated at all — its property function does not run. The measurement below shows exactly that, and it is the opposite of the folklore.",[590,709,710,711,714,715,718],{},"So the accurate mental model is two-tier. Exclusion ",[593,712,713],{},"can"," save you the cost of a derived value. It ",[593,716,717],{},"cannot"," save you the cost, or the exposure, of a stored one.",[720,721,722,840],"figure",{},[723,724,732,736,740,749,756,761,765,769,771,775,780,783,787,791,794,801,806,810,813,817,820,826,832,835],"svg",{"viewBox":725,"role":726,"ariaLabelledBy":727,"xmlns":730,"style":731},"0 0 720 250","img",[728,729],"ex-title","ex-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0",[733,734,735],"title",{"id":728},"Where per-endpoint exclusion happens in the response pipeline",[737,738,739],"desc",{"id":729},"The row is loaded and the model built, the endpoint returns it, then serialization applies the exclusion parameters and only the filtered result is sent. Everything before the exclusion step has already happened.",[741,742],"rect",{"x":743,"y":744,"width":745,"height":746,"rx":747,"style":748},"20","70","140","58","8","fill:none;stroke:currentColor;stroke-width:1.4",[750,751,755],"text",{"x":752,"y":753,"style":754},"90","95","text-anchor:middle;fill:currentColor;font:500 12px sans-serif","load and build",[750,757,760],{"x":752,"y":758,"style":759},"113","text-anchor:middle;fill:currentColor;font:400 11px sans-serif","every field held",[741,762],{"x":763,"y":744,"width":764,"height":746,"rx":747,"style":748},"196","164",[750,766,768],{"x":767,"y":753,"style":754},"278","endpoint returns",[750,770,686],{"x":767,"y":758,"style":759},[741,772],{"x":773,"y":744,"width":764,"height":746,"rx":747,"style":774},"396","fill:none;stroke:#00796B;stroke-width:1.8",[750,776,779],{"x":777,"y":753,"style":778},"478","text-anchor:middle;fill:#00796B;font:600 12px sans-serif","apply exclusion",[750,781,782],{"x":777,"y":758,"style":759},"filter the output",[741,784],{"x":785,"y":744,"width":786,"height":746,"rx":747,"style":748},"596","104",[750,788,790],{"x":789,"y":753,"style":754},"648","JSON body",[750,792,793],{"x":789,"y":758,"style":759},"sent",[795,796],"line",{"x1":797,"y1":798,"x2":799,"y2":798,"style":800},"160","99","188","stroke:currentColor;stroke-width:1.5",[802,803],"polygon",{"points":804,"style":805},"188,95 196,99 188,103","fill:currentColor",[795,807],{"x1":808,"y1":798,"x2":809,"y2":798,"style":800},"360","388",[802,811],{"points":812,"style":805},"388,95 396,99 388,103",[795,814],{"x1":815,"y1":798,"x2":816,"y2":798,"style":800},"560","588",[802,818],{"points":819,"style":805},"588,95 596,99 588,103",[795,821],{"x1":822,"y1":823,"x2":822,"y2":824,"style":825},"150","128","166","stroke:currentColor;stroke-width:1.3;stroke-dasharray:4 3",[750,827,831],{"x":828,"y":829,"style":830},"180","184","text-anchor:middle;fill:currentColor;font:400 11.5px sans-serif","stored values already read and held",[795,833],{"x1":777,"y1":823,"x2":777,"y2":824,"style":834},"stroke:#00796B;stroke-width:1.3;stroke-dasharray:4 3",[750,836,839],{"x":777,"y":837,"style":838},"202","text-anchor:middle;fill:#00796B;font:400 11.5px sans-serif","excluded computed fields skipped here",[841,842,843],"figcaption",{},"Exclusion is the last step, so it can skip a derived value but never unwinds the work that produced a stored one.",[659,845,847],{"id":846},"prerequisites","Prerequisites",[597,849,850,853],{},[600,851,852],{},"FastAPI 0.139.2 and Pydantic 2.13.4, the versions all output below was produced on.",[600,854,855,856,858],{},"A response model with a nested submodel, an optional field, and a ",[603,857,647],{}," — so each parameter has something visible to act on.",[659,860,862],{"id":861},"the-model-under-test","The Model Under Test",[590,864,865,868,869,872],{},[603,866,867],{},"COMPUTED"," and ",[603,870,871],{},"VALIDATED"," are module-level lists the model appends to, so the measurement later on can count how often each piece of work actually ran.",[874,875,880],"pre",{"className":876,"code":877,"language":878,"meta":879,"style":879},"language-python shiki shiki-themes github-light-high-contrast","class Address(BaseModel):\n    street: str\n    city: str\n    postcode: str | None = None\n    internal_geocode: str = \"51.5,-0.12\"\n\n\nclass User(BaseModel):\n    id: int\n    email: str\n    display_name: str | None = None\n    password_hash: str\n    address: Address\n\n    @field_validator(\"password_hash\")\n    @classmethod\n    def record_validation(cls, value: str) -> str:\n        # Fires whenever the response model is validated, excluded or not.\n        VALIDATED.append(\"validated password_hash\")\n        return value\n\n    @computed_field\n    @property\n    def domain(self) -> str:\n        # Fires only when the field survives the exclusion selection.\n        COMPUTED.append(f\"computed domain for user {self.id}\")\n        return self.email.split(\"@\")[-1]\n","python","",[603,881,882,905,914,922,943,957,964,969,983,995,1003,1019,1027,1033,1038,1053,1062,1084,1091,1105,1114,1119,1125,1133,1148,1154,1185],{"__ignoreMap":879},[883,884,886,890,894,898,902],"span",{"class":795,"line":885},1,[883,887,889],{"class":888},"sTJeM","class",[883,891,893],{"class":892},"sV4o_"," Address",[883,895,897],{"class":896},"sigWx","(",[883,899,901],{"class":900},"sacAq","BaseModel",[883,903,904],{"class":896},"):\n",[883,906,908,911],{"class":795,"line":907},2,[883,909,910],{"class":896},"    street: ",[883,912,913],{"class":900},"str\n",[883,915,917,920],{"class":795,"line":916},3,[883,918,919],{"class":896},"    city: ",[883,921,913],{"class":900},[883,923,925,928,931,934,937,940],{"class":795,"line":924},4,[883,926,927],{"class":896},"    postcode: ",[883,929,930],{"class":900},"str",[883,932,933],{"class":888}," |",[883,935,936],{"class":900}," None",[883,938,939],{"class":888}," =",[883,941,942],{"class":900}," None\n",[883,944,946,949,951,953],{"class":795,"line":945},5,[883,947,948],{"class":896},"    internal_geocode: ",[883,950,930],{"class":900},[883,952,939],{"class":888},[883,954,956],{"class":955},"sYEJz"," \"51.5,-0.12\"\n",[883,958,960],{"class":795,"line":959},6,[883,961,963],{"emptyLinePlaceholder":962},true,"\n",[883,965,967],{"class":795,"line":966},7,[883,968,963],{"emptyLinePlaceholder":962},[883,970,972,974,977,979,981],{"class":795,"line":971},8,[883,973,889],{"class":888},[883,975,976],{"class":892}," User",[883,978,897],{"class":896},[883,980,901],{"class":900},[883,982,904],{"class":896},[883,984,986,989,992],{"class":795,"line":985},9,[883,987,988],{"class":900},"    id",[883,990,991],{"class":896},": ",[883,993,994],{"class":900},"int\n",[883,996,998,1001],{"class":795,"line":997},10,[883,999,1000],{"class":896},"    email: ",[883,1002,913],{"class":900},[883,1004,1006,1009,1011,1013,1015,1017],{"class":795,"line":1005},11,[883,1007,1008],{"class":896},"    display_name: ",[883,1010,930],{"class":900},[883,1012,933],{"class":888},[883,1014,936],{"class":900},[883,1016,939],{"class":888},[883,1018,942],{"class":900},[883,1020,1022,1025],{"class":795,"line":1021},12,[883,1023,1024],{"class":896},"    password_hash: ",[883,1026,913],{"class":900},[883,1028,1030],{"class":795,"line":1029},13,[883,1031,1032],{"class":896},"    address: Address\n",[883,1034,1036],{"class":795,"line":1035},14,[883,1037,963],{"emptyLinePlaceholder":962},[883,1039,1041,1045,1047,1050],{"class":795,"line":1040},15,[883,1042,1044],{"class":1043},"s3dhs","    @field_validator",[883,1046,897],{"class":896},[883,1048,1049],{"class":955},"\"password_hash\"",[883,1051,1052],{"class":896},")\n",[883,1054,1056,1059],{"class":795,"line":1055},16,[883,1057,1058],{"class":1043},"    @",[883,1060,1061],{"class":900},"classmethod\n",[883,1063,1065,1068,1071,1074,1076,1079,1081],{"class":795,"line":1064},17,[883,1066,1067],{"class":888},"    def",[883,1069,1070],{"class":1043}," record_validation",[883,1072,1073],{"class":896},"(cls, value: ",[883,1075,930],{"class":900},[883,1077,1078],{"class":896},") -> ",[883,1080,930],{"class":900},[883,1082,1083],{"class":896},":\n",[883,1085,1087],{"class":795,"line":1086},18,[883,1088,1090],{"class":1089},"sFeEa","        # Fires whenever the response model is validated, excluded or not.\n",[883,1092,1094,1097,1100,1103],{"class":795,"line":1093},19,[883,1095,1096],{"class":900},"        VALIDATED",[883,1098,1099],{"class":896},".append(",[883,1101,1102],{"class":955},"\"validated password_hash\"",[883,1104,1052],{"class":896},[883,1106,1108,1111],{"class":795,"line":1107},20,[883,1109,1110],{"class":888},"        return",[883,1112,1113],{"class":896}," value\n",[883,1115,1117],{"class":795,"line":1116},21,[883,1118,963],{"emptyLinePlaceholder":962},[883,1120,1122],{"class":795,"line":1121},22,[883,1123,1124],{"class":1043},"    @computed_field\n",[883,1126,1128,1130],{"class":795,"line":1127},23,[883,1129,1058],{"class":1043},[883,1131,1132],{"class":900},"property\n",[883,1134,1136,1138,1141,1144,1146],{"class":795,"line":1135},24,[883,1137,1067],{"class":888},[883,1139,1140],{"class":1043}," domain",[883,1142,1143],{"class":896},"(self) -> ",[883,1145,930],{"class":900},[883,1147,1083],{"class":896},[883,1149,1151],{"class":795,"line":1150},25,[883,1152,1153],{"class":1089},"        # Fires only when the field survives the exclusion selection.\n",[883,1155,1157,1160,1162,1165,1168,1171,1174,1177,1180,1183],{"class":795,"line":1156},26,[883,1158,1159],{"class":900},"        COMPUTED",[883,1161,1099],{"class":896},[883,1163,1164],{"class":888},"f",[883,1166,1167],{"class":955},"\"computed domain for user ",[883,1169,1170],{"class":888},"{",[883,1172,1173],{"class":900},"self",[883,1175,1176],{"class":896},".id",[883,1178,1179],{"class":888},"}",[883,1181,1182],{"class":955},"\"",[883,1184,1052],{"class":896},[883,1186,1188,1190,1193,1196,1199,1202,1205,1208],{"class":795,"line":1187},27,[883,1189,1110],{"class":888},[883,1191,1192],{"class":900}," self",[883,1194,1195],{"class":896},".email.split(",[883,1197,1198],{"class":955},"\"@\"",[883,1200,1201],{"class":896},")[",[883,1203,1204],{"class":888},"-",[883,1206,1207],{"class":900},"1",[883,1209,1210],{"class":896},"]\n",[590,1212,1213,1214,1217,1218,1221,1222,868,1225,1228],{},"Two instances are served: ",[603,1215,1216],{},"FULL"," has every field set explicitly, and ",[603,1219,1220],{},"PARTIAL"," omits ",[603,1223,1224],{},"display_name",[603,1226,1227],{},"postcode"," so the \"unset\" and \"none\" variants have something to differ on.",[659,1230,1232],{"id":1231},"the-baseline","The Baseline",[874,1234,1238],{"className":1235,"code":1237,"language":750,"meta":879},[1236],"language-text","$ GET \u002Fusers\u002Ffull\n200 OK\n{\n  \"id\": 1,\n  \"email\": \"ada@example.com\",\n  \"display_name\": \"Ada\",\n  \"password_hash\": \"$2b$12$abcdefghijklmnopqrstuv\",\n  \"address\": {\n    \"street\": \"12 Bridge St\",\n    \"city\": \"London\",\n    \"postcode\": \"EC1A 1BB\",\n    \"internal_geocode\": \"51.5,-0.12\"\n  },\n  \"domain\": \"example.com\"\n}\n",[603,1239,1237],{"__ignoreMap":879},[590,1241,1242,1243,636],{},"Everything, including the hash and the internal geocode. All output on this page comes from ",[603,1244,1245],{},"_verify\u002Foutput\u002Fpyd-exclude-per-endpoint.txt",[659,1247,1249,1250],{"id":1248},"variant-1-response_model_exclude","Variant 1: ",[603,1251,605],{},[874,1253,1255],{"className":876,"code":1254,"language":878,"meta":879,"style":879},"@app.get(\"\u002Fusers\u002Fexclude\", response_model=User, response_model_exclude={\"password_hash\"})\nasync def read_excluded() -> User:\n    return FULL\n",[603,1256,1257,1289,1303],{"__ignoreMap":879},[883,1258,1259,1262,1264,1267,1270,1272,1275,1278,1280,1282,1284,1286],{"class":795,"line":885},[883,1260,1261],{"class":1043},"@app.get",[883,1263,897],{"class":896},[883,1265,1266],{"class":955},"\"\u002Fusers\u002Fexclude\"",[883,1268,1269],{"class":896},", ",[883,1271,686],{"class":892},[883,1273,1274],{"class":888},"=",[883,1276,1277],{"class":896},"User, ",[883,1279,605],{"class":892},[883,1281,1274],{"class":888},[883,1283,1170],{"class":896},[883,1285,1049],{"class":955},[883,1287,1288],{"class":896},"})\n",[883,1290,1291,1294,1297,1300],{"class":795,"line":907},[883,1292,1293],{"class":888},"async",[883,1295,1296],{"class":888}," def",[883,1298,1299],{"class":1043}," read_excluded",[883,1301,1302],{"class":896},"() -> User:\n",[883,1304,1305,1308],{"class":795,"line":916},[883,1306,1307],{"class":888},"    return",[883,1309,1310],{"class":900}," FULL\n",[874,1312,1315],{"className":1313,"code":1314,"language":750,"meta":879},[1236],"$ GET \u002Fusers\u002Fexclude\n200 OK\n{\n  \"id\": 1,\n  \"email\": \"ada@example.com\",\n  \"display_name\": \"Ada\",\n  \"address\": {\n    \"street\": \"12 Bridge St\",\n    \"city\": \"London\",\n    \"postcode\": \"EC1A 1BB\",\n    \"internal_geocode\": \"51.5,-0.12\"\n  },\n  \"domain\": \"example.com\"\n}\n",[603,1316,1314],{"__ignoreMap":879},[590,1318,1319,1321,1322,1325],{},[603,1320,700],{}," is gone; the nested ",[603,1323,1324],{},"internal_geocode"," is not, because a top-level set says nothing about nested models.",[659,1327,1329],{"id":1328},"variant-2-nested-exclusion","Variant 2: Nested Exclusion",[590,1331,1332,1333,1336],{},"To reach inside, pass a dict instead of a set. Values are either ",[603,1334,1335],{},"True"," (drop the whole thing) or a nested selection.",[874,1338,1340],{"className":876,"code":1339,"language":878,"meta":879,"style":879},"@app.get(\n    \"\u002Fusers\u002Fexclude-nested\",\n    response_model=User,\n    response_model_exclude={\"password_hash\": True, \"address\": {\"internal_geocode\"}},\n)\nasync def read_excluded_nested() -> User:\n    return FULL\n",[603,1341,1342,1349,1357,1367,1396,1400,1411],{"__ignoreMap":879},[883,1343,1344,1346],{"class":795,"line":885},[883,1345,1261],{"class":1043},[883,1347,1348],{"class":896},"(\n",[883,1350,1351,1354],{"class":795,"line":907},[883,1352,1353],{"class":955},"    \"\u002Fusers\u002Fexclude-nested\"",[883,1355,1356],{"class":896},",\n",[883,1358,1359,1362,1364],{"class":795,"line":916},[883,1360,1361],{"class":892},"    response_model",[883,1363,1274],{"class":888},[883,1365,1366],{"class":896},"User,\n",[883,1368,1369,1372,1374,1376,1378,1380,1382,1384,1387,1390,1393],{"class":795,"line":924},[883,1370,1371],{"class":892},"    response_model_exclude",[883,1373,1274],{"class":888},[883,1375,1170],{"class":896},[883,1377,1049],{"class":955},[883,1379,991],{"class":896},[883,1381,1335],{"class":900},[883,1383,1269],{"class":896},[883,1385,1386],{"class":955},"\"address\"",[883,1388,1389],{"class":896},": {",[883,1391,1392],{"class":955},"\"internal_geocode\"",[883,1394,1395],{"class":896},"}},\n",[883,1397,1398],{"class":795,"line":945},[883,1399,1052],{"class":896},[883,1401,1402,1404,1406,1409],{"class":795,"line":959},[883,1403,1293],{"class":888},[883,1405,1296],{"class":888},[883,1407,1408],{"class":1043}," read_excluded_nested",[883,1410,1302],{"class":896},[883,1412,1413,1415],{"class":795,"line":966},[883,1414,1307],{"class":888},[883,1416,1310],{"class":900},[874,1418,1421],{"className":1419,"code":1420,"language":750,"meta":879},[1236],"$ GET \u002Fusers\u002Fexclude-nested\n200 OK\n{\n  \"id\": 1,\n  \"email\": \"ada@example.com\",\n  \"display_name\": \"Ada\",\n  \"address\": {\n    \"street\": \"12 Bridge St\",\n    \"city\": \"London\",\n    \"postcode\": \"EC1A 1BB\"\n  },\n  \"domain\": \"example.com\"\n}\n",[603,1422,1420],{"__ignoreMap":879},[590,1424,1425,1426,1429],{},"The nesting composes to any depth the model has. For lists of submodels the same syntax applies with ",[603,1427,1428],{},"\"__all__\""," as the key meaning \"every element\".",[659,1431,1433,1434],{"id":1432},"variant-3-exclude_unset","Variant 3: ",[603,1435,1436],{},"exclude_unset",[590,1438,1439,1440,1442,1443,1445,1446,636],{},"Applied to ",[603,1441,1220],{},", which was constructed without ",[603,1444,1224],{}," and without a nested ",[603,1447,1227],{},[874,1449,1452],{"className":1450,"code":1451,"language":750,"meta":879},[1236],"$ GET \u002Fusers\u002Fexclude-unset\n200 OK\n{\n  \"id\": 2,\n  \"email\": \"grace@example.com\",\n  \"password_hash\": \"$2b$12$zyxwvutsrqponmlkjihgfe\",\n  \"address\": {\n    \"street\": \"3 Navy Yard\",\n    \"city\": \"Arlington\"\n  },\n  \"domain\": \"example.com\"\n}\n",[603,1453,1451],{"__ignoreMap":879},[590,1455,1456,1457,1459,1460,1462,1463,1465,1466,1468,1469,1471,1472,1475,1476,1479,1480,1483],{},"Three things vanished: ",[603,1458,1224],{},", nested ",[603,1461,1227],{},", and nested ",[603,1464,1324],{},". The last one is the instructive case — ",[603,1467,1324],{}," has a non-",[603,1470,619],{}," default of ",[603,1473,1474],{},"\"51.5,-0.12\""," and was still dropped, because \"unset\" is about whether a value was ",[641,1477,1478],{},"supplied",", not about what the value is. Note also that the flag recursed into ",[603,1481,1482],{},"Address"," without being asked to.",[590,1485,1486,1487,1489],{},"This is what makes ",[603,1488,1436],{}," right for PATCH-style responses and delta payloads, where the distinction between \"not mentioned\" and \"explicitly set to the default\" is the whole point. It is wrong for a general read endpoint, where clients reasonably expect a stable set of keys and instead get a shape that varies per row depending on how it happened to be constructed.",[659,1491,1493,1494],{"id":1492},"variant-4-exclude_none","Variant 4: ",[603,1495,1496],{},"exclude_none",[590,1498,1499,1500,1502],{},"Same ",[603,1501,1220],{}," instance, different flag:",[874,1504,1507],{"className":1505,"code":1506,"language":750,"meta":879},[1236],"$ GET \u002Fusers\u002Fexclude-none\n200 OK\n{\n  \"id\": 2,\n  \"email\": \"grace@example.com\",\n  \"password_hash\": \"$2b$12$zyxwvutsrqponmlkjihgfe\",\n  \"address\": {\n    \"street\": \"3 Navy Yard\",\n    \"city\": \"Arlington\",\n    \"internal_geocode\": \"51.5,-0.12\"\n  },\n  \"domain\": \"example.com\"\n}\n",[603,1508,1506],{"__ignoreMap":879},[590,1510,1511,868,1513,1515,1516,1518,1519,1521,1522,1525,1526,1528,1529,1531],{},[603,1512,1224],{},[603,1514,1227],{}," are dropped because they are ",[603,1517,619],{},". ",[603,1520,1324],{}," ",[593,1523,1524],{},"survives"," here, because its value is a string — the exact case where the two flags diverge. Choose ",[603,1527,1496],{}," when the client treats absence and null identically and you want smaller payloads; choose ",[603,1530,1436],{}," when null is a meaningful, distinct signal.",[659,1533,1535,1536],{"id":1534},"variant-5-response_model_include","Variant 5: ",[603,1537,609],{},[590,1539,1540],{},"The allow-list. Safer for narrow projections because adding a field to the model does not silently add it to the response.",[874,1542,1545],{"className":1543,"code":1544,"language":750,"meta":879},[1236],"$ GET \u002Fusers\u002Finclude-only\n200 OK\n{\n  \"id\": 1,\n  \"email\": \"ada@example.com\"\n}\n",[603,1546,1544],{"__ignoreMap":879},[590,1548,1549,1550,1553,1554,1556],{},"Note ",[603,1551,1552],{},"domain"," is absent even though it is a ",[603,1555,647],{}," — include applies to computed fields as well.",[659,1558,1560],{"id":1559},"measuring-what-exclusion-actually-skips","Measuring What Exclusion Actually Skips",[590,1562,1563,1565,1566,1569,1570,1572],{},[603,1564,1552],{},"'s property appends to a counter each time it is evaluated. The ",[603,1567,1568],{},"\u002Faudit"," endpoint clears the counter, runs ",[603,1571,690],{}," with four different selections against the same instance, and reports what happened:",[874,1574,1577],{"className":1575,"code":1576,"language":750,"meta":879},[1236],"$ GET \u002Faudit\n200 OK\n{\n  \"no exclusion\": {\n    \"keys\": [\n      \"address\",\n      \"display_name\",\n      \"domain\",\n      \"email\",\n      \"id\",\n      \"password_hash\"\n    ],\n    \"domain_property_evaluated\": 1,\n    \"password_hash_validator_ran\": 0\n  },\n  \"exclude password_hash\": {\n    \"keys\": [\n      \"address\",\n      \"display_name\",\n      \"domain\",\n      \"email\",\n      \"id\"\n    ],\n    \"domain_property_evaluated\": 1,\n    \"password_hash_validator_ran\": 0\n  },\n  \"exclude domain\": {\n    \"keys\": [\n      \"address\",\n      \"display_name\",\n      \"email\",\n      \"id\",\n      \"password_hash\"\n    ],\n    \"domain_property_evaluated\": 0,\n    \"password_hash_validator_ran\": 0\n  },\n  \"include id+email only\": {\n    \"keys\": [\n      \"email\",\n      \"id\"\n    ],\n    \"domain_property_evaluated\": 0,\n    \"password_hash_validator_ran\": 0\n  }\n}\n",[603,1578,1576],{"__ignoreMap":879},[590,1580,1581,1582,1585,1586,1588,1589,1592,1593,1596,1597,1599,1600,1602,1603,1605,1606,1609],{},"Read the ",[603,1583,1584],{},"domain_property_evaluated"," column down the page. When ",[603,1587,1552],{}," survives the selection it is evaluated once. When it is excluded — directly, or by being left out of an ",[603,1590,1591],{},"include"," set — it is evaluated ",[593,1594,1595],{},"zero"," times. Pydantic resolves the selection before walking the fields, so a ",[603,1598,647],{}," you do not ask for genuinely costs nothing. If you have been avoiding ",[603,1601,647],{}," for expensive derivations because you assumed it always runs, that assumption is wrong on Pydantic 2.13.4, and per-route ",[603,1604,1591],{},"\u002F",[603,1607,1608],{},"exclude"," is a legitimate way to make an expensive projection optional.",[590,1611,1612,1613,1616,1617,1619],{},"Now read ",[603,1614,1615],{},"password_hash_validator_ran",", which stays at zero even in the \"no exclusion\" row. That is the other half of the picture: serialization does not re-validate. The field validator on ",[603,1618,700],{}," fired exactly once, when the instance was constructed, long before any of these dumps. By the time exclusion is applied the hash has been selected from the database, coerced, validated and held in memory for the duration of the request. Excluding it changes what is printed and nothing else.",[590,1621,1622,1623,636],{},"Hence the security rule. Any exception raised between construction and serialization can surface that value in a traceback; any route where someone forgets the parameter ships it; and the OpenAPI schema advertises it on every one of these endpoints regardless. If a field must never leave the process, the model the endpoint returns must not have that field. Exclusion is a projection tool, not a boundary. For the cost side of the same question, see ",[653,1624,1626],{"href":1625},"\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance\u002F","Pydantic model serialization performance",[659,1628,1630],{"id":1629},"edge-cases-and-gotchas","Edge Cases and Gotchas",[597,1632,1633,1645,1653,1661,1678],{},[600,1634,1635,1638,1639,1641,1642,1644],{},[593,1636,1637],{},"The schema does not change."," All five endpoints document the full ",[603,1640,668],{},", including ",[603,1643,700],{},". Generated clients will declare fields the server never sends. If the contract matters, use separate response models.",[600,1646,1647,1652],{},[593,1648,1649,1651],{},[603,1650,605],{}," is per route, not per router."," There is no inherited default; every path operation repeats the parameter, and every omission is a leak.",[600,1654,1655,1660],{},[593,1656,1657,1659],{},[603,1658,1436],{}," needs a real model instance."," Returning a plain dict from the endpoint means FastAPI validates it into the response model, and every key present in that dict counts as set. The \"unset\" information comes from the object you return, so construct the model yourself.",[600,1662,1663,1521,1666,1669,1670,1673,1674,1677],{},[593,1664,1665],{},"Sets versus dicts.",[603,1667,1668],{},"{\"a\", \"b\"}"," is a set of two fields. ",[603,1671,1672],{},"{\"a\": True}"," is a dict. ",[603,1675,1676],{},"{\"a\"}"," inside a dict value is a nested set. Mixing them up produces confusing, silent results.",[600,1679,1680,1686,1687,1691],{},[593,1681,1682,1683,636],{},"Interaction with ",[603,1684,1685],{},"model_serializer"," A model whose output is produced by a ",[653,1688,1690],{"href":1689},"\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Freplacing-json-encoders-with-field-serializer\u002F","custom model serializer"," builds its own dict, so field-name-based exclusion no longer lines up with the emitted keys.",[659,1693,1695],{"id":1694},"verification","Verification",[590,1697,1698],{},"Assert the exact key set, not just the absence of the field you were thinking about:",[874,1700,1702],{"className":876,"code":1701,"language":878,"meta":879,"style":879},"def test_public_profile_omits_hash():\n    body = client.get(\"\u002Fusers\u002Fexclude\").json()\n    assert set(body) == {\"id\", \"email\", \"display_name\", \"address\", \"domain\"}\n\n\ndef test_exclude_unset_recurses():\n    body = client.get(\"\u002Fusers\u002Fexclude-unset\").json()\n    assert \"postcode\" not in body[\"address\"]\n",[603,1703,1704,1715,1730,1772,1776,1780,1789,1802],{"__ignoreMap":879},[883,1705,1706,1709,1712],{"class":795,"line":885},[883,1707,1708],{"class":888},"def",[883,1710,1711],{"class":1043}," test_public_profile_omits_hash",[883,1713,1714],{"class":896},"():\n",[883,1716,1717,1720,1722,1725,1727],{"class":795,"line":907},[883,1718,1719],{"class":896},"    body ",[883,1721,1274],{"class":888},[883,1723,1724],{"class":896}," client.get(",[883,1726,1266],{"class":955},[883,1728,1729],{"class":896},").json()\n",[883,1731,1732,1735,1738,1741,1744,1747,1750,1752,1755,1757,1760,1762,1764,1766,1769],{"class":795,"line":916},[883,1733,1734],{"class":888},"    assert",[883,1736,1737],{"class":900}," set",[883,1739,1740],{"class":896},"(body) ",[883,1742,1743],{"class":888},"==",[883,1745,1746],{"class":896}," {",[883,1748,1749],{"class":955},"\"id\"",[883,1751,1269],{"class":896},[883,1753,1754],{"class":955},"\"email\"",[883,1756,1269],{"class":896},[883,1758,1759],{"class":955},"\"display_name\"",[883,1761,1269],{"class":896},[883,1763,1386],{"class":955},[883,1765,1269],{"class":896},[883,1767,1768],{"class":955},"\"domain\"",[883,1770,1771],{"class":896},"}\n",[883,1773,1774],{"class":795,"line":924},[883,1775,963],{"emptyLinePlaceholder":962},[883,1777,1778],{"class":795,"line":945},[883,1779,963],{"emptyLinePlaceholder":962},[883,1781,1782,1784,1787],{"class":795,"line":959},[883,1783,1708],{"class":888},[883,1785,1786],{"class":1043}," test_exclude_unset_recurses",[883,1788,1714],{"class":896},[883,1790,1791,1793,1795,1797,1800],{"class":795,"line":966},[883,1792,1719],{"class":896},[883,1794,1274],{"class":888},[883,1796,1724],{"class":896},[883,1798,1799],{"class":955},"\"\u002Fusers\u002Fexclude-unset\"",[883,1801,1729],{"class":896},[883,1803,1804,1806,1809,1812,1815,1818,1820],{"class":795,"line":971},[883,1805,1734],{"class":888},[883,1807,1808],{"class":955}," \"postcode\"",[883,1810,1811],{"class":888}," not",[883,1813,1814],{"class":888}," in",[883,1816,1817],{"class":896}," body[",[883,1819,1386],{"class":955},[883,1821,1210],{"class":896},[590,1823,1824,1825,1827],{},"The equality assertion is the important one: it fails when someone adds a field to ",[603,1826,668],{},", which is exactly the moment you want to be told that a route's projection has changed.",[659,1829,1831],{"id":1830},"trade-offs-and-when-not-to","Trade-offs and When Not To",[590,1833,1834,1835,1838],{},"Per-route parameters are the right tool when the ",[641,1836,1837],{},"shape"," of one model is genuinely the same across endpoints and only the projection differs — a mobile variant, a compact list view, a delta response. They keep one source of truth and avoid a class explosion.",[590,1840,1841],{},"They are the wrong tool when the difference is a contract difference. Public and admin views of a user are two contracts, and expressing that as an argument on a decorator means the difference is invisible in the type system, absent from the schema, and one deleted parameter away from a disclosure incident. Two models with a shared base cost a few lines and make the boundary structural.",[590,1843,1844],{},"The practical rule: if the excluded field is merely uninteresting, or is a derived value you want to make optional, use the parameter — the measurement above shows the derivation is genuinely skipped. If the field is sensitive, use a different model, because no parameter can un-load a value the query already returned.",[659,1846,1848],{"id":1847},"faq","FAQ",[590,1850,1851,1854,1856,1857,1859],{},[593,1852,1853],{},"What is the difference between response_model_exclude and exclude_unset?",[603,1855,605],{}," names specific fields to drop, whatever their value. ",[603,1858,1436],{}," drops every field the object was never explicitly given, so defaults disappear regardless of what they are. They are independent and can be combined on the same route.",[590,1861,1862,1865],{},[593,1863,1864],{},"Does response_model_exclude remove a field from the OpenAPI schema?","\nNo. The generated schema still describes the full response model, so a generated client will expect a field the endpoint never sends. If the field must not appear in the contract, define a separate response model instead.",[590,1867,1868,1871,1872,1874],{},[593,1869,1870],{},"Are excluded fields still computed before they are removed?","\nYes. Validation against the response model runs first and exclusion is applied to the resulting output, so a ",[603,1873,647],{}," runs and any expensive property is evaluated even when the field is then dropped. Exclusion saves bytes on the wire, not work.",[590,1876,1877,1880,1881,1883],{},[593,1878,1879],{},"How do I exclude a field inside a nested model?","\nPass a dict instead of a set, mapping the parent field name to the nested selection, for example ",[603,1882,635],{},". The nesting can go as deep as the model does.",[590,1885,1886,1889],{},[593,1887,1888],{},"Is response_model_exclude safe for hiding secrets?","\nIt is not a security boundary. The value is loaded, validated and computed before removal, it remains in the OpenAPI schema, and one route missing the parameter leaks it. A dedicated response model that has no such field is the only structural guarantee.",[659,1891,1893],{"id":1892},"related-reading","Related Reading",[597,1895,1896,1903,1914,1919],{},[600,1897,1898,1521,1901,636],{},[593,1899,1900],{},"Up to the topic:",[653,1902,656],{"href":655},[600,1904,1905,1906,868,1910,636],{},"For structures where exclusion has to recurse indefinitely, see ",[653,1907,1909],{"href":1908},"\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fself-referencing-and-recursive-models\u002F","self-referencing and recursive models",[653,1911,1913],{"href":1912},"\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fhandling-deeply-nested-json-models-efficiently\u002F","handling deeply nested JSON models efficiently",[600,1915,1916,1917,636],{},"The cost of computing fields you then drop is quantified in ",[653,1918,1626],{"href":1625},[600,1920,1921,1922,636],{},"To change the shape of what is emitted rather than which keys survive, see ",[653,1923,1924],{"href":1689},"replacing json_encoders with field_serializer",[1926,1927,1928],"style",{},"html pre.shiki code .sTJeM, html code.shiki .sTJeM{--shiki-default:#A0111F}html pre.shiki code .sV4o_, html code.shiki .sV4o_{--shiki-default:#702C00}html pre.shiki code .sigWx, html code.shiki .sigWx{--shiki-default:#0E1116}html pre.shiki code .sacAq, html code.shiki .sacAq{--shiki-default:#023B95}html pre.shiki code .sYEJz, html code.shiki .sYEJz{--shiki-default:#032563}html pre.shiki code .s3dhs, html code.shiki .s3dhs{--shiki-default:#622CBC}html pre.shiki code .sFeEa, html code.shiki .sFeEa{--shiki-default:#66707B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":879,"searchDepth":907,"depth":907,"links":1930},[1931,1932,1933,1934,1935,1936,1938,1939,1941,1943,1945,1946,1947,1948,1949,1950],{"id":661,"depth":907,"text":662},{"id":679,"depth":907,"text":680},{"id":846,"depth":907,"text":847},{"id":861,"depth":907,"text":862},{"id":1231,"depth":907,"text":1232},{"id":1248,"depth":907,"text":1937},"Variant 1: response_model_exclude",{"id":1328,"depth":907,"text":1329},{"id":1432,"depth":907,"text":1940},"Variant 3: exclude_unset",{"id":1492,"depth":907,"text":1942},"Variant 4: exclude_none",{"id":1534,"depth":907,"text":1944},"Variant 5: response_model_include",{"id":1559,"depth":907,"text":1560},{"id":1629,"depth":907,"text":1630},{"id":1694,"depth":907,"text":1695},{"id":1830,"depth":907,"text":1831},{"id":1847,"depth":907,"text":1848},{"id":1892,"depth":907,"text":1893},"2026-07-20","Use response_model_exclude, exclude_unset and exclude_none per route, with nested exclusion syntax and a measurement of what exclusion actually skips computing.","md",[1955,1957,1959,1961,1963],{"q":1853,"a":1956},"response_model_exclude names specific fields to drop, whatever their value. exclude_unset drops every field the object was never explicitly given, so defaults disappear regardless of what they are. They are independent and can be combined on the same route.",{"q":1864,"a":1958},"No. The generated schema still describes the full response model, so a generated client will expect a field the endpoint never sends. If the field must not appear in the contract, define a separate response model instead.",{"q":1870,"a":1960},"A computed_field that is excluded is not evaluated, because the selection is applied inside the serializer before the property is called. Ordinary fields are a different matter: exclusion runs long after the value was fetched, validated and held in memory, so it saves bytes on the wire but no work upstream.",{"q":1879,"a":1962},"Pass a dict instead of a set, mapping the parent field name to the nested selection, for example {\"password_hash\": True, \"address\": {\"internal_geocode\"}}. The nesting can go as deep as the model does.",{"q":1888,"a":1964},"It is not a security boundary. The value is loaded, validated and computed before removal, it remains in the OpenAPI schema, and one route missing the parameter leaks it. A dedicated response model that has no such field is the only structural guarantee.",null,{"slug":1967,"breadcrumb":1968},"excluding-fields-per-endpoint",[1969,1971,1974,1976],{"label":1970,"path":1605},"Home",{"label":1972,"path":1973},"Advanced Pydantic Validation & Serialization","\u002Fadvanced-pydantic-validation-serialization\u002F",{"label":1975,"path":655},"Nested Model Serialization",{"label":1977,"path":1978},"Excluding Fields Per Endpoint","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fexcluding-fields-per-endpoint\u002F",{"title":73,"description":1952},"article","cNx467MQI7yBp8aBrc3TDdvuYy15Cv6rp7NUDauKmt8",[1965,1965],1784588202620]