text: Title: Dependency Models created from Form input data are loosing metadata(field set) and are enforcing validation on default values.
  Body: 
  ### Discussed in https://github.com/fastapi/fastapi/discussions/13380
  
  <div type='discussions-op-text'>
  
  <sup>Originally posted by **sneakers-the-rat** February 16, 2025</sup>
  ### First Check
  
  - [X] I added a very descriptive title here.
  - [X] I used the GitHub search to find a similar question and didn't find it.
  - [X] I searched the FastAPI documentation, with the integrated search.
  - [X] I already searched in Google "How to X in FastAPI" and didn't find any information.
  - [X] I already read and followed all the tutorial in the docs and didn't find an answer.
  - [X] I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/pydantic/pydantic).
  - [X] I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui).
  - [X] I already checked if it is not related to FastAPI but to [ReDoc](https://github.com/Redocly/redoc).
  
  ### Commit to Help
  
  - [X] I commit to help with one of those options 👆
  
  ### Example Code
  
  File: fastapi_defaults_bug.py
  ```python
  import uvicorn
  from typing import Annotated
  from pydantic import BaseModel, Field
  
  from fastapi import FastAPI, Form
  
  
  class ExampleJsonModel(BaseModel):
      sample_field_1: Annotated[bool, Field(default=True)]
      sample_field_2: Annotated[bool, Field(default=False)]
      sample_field_3: Annotated[bool, Field(default=None)]
      sample_field_4: Annotated[str, Field(default=0)] # This is dangerous but can be used with a validator
  
  
  class ExampleFormModel(BaseModel):
      sample_field_1: Annotated[bool, Form(default=True)]
      sample_field_2: Annotated[bool, Form(default=False)]
      sample_field_3: Annotated[bool, Form(default=None)]
      sample_field_4: Annotated[str, Form(default=0)] # This is dangerous but can be used with a validator
  
  
  class ResponseSampleModel(BaseModel):
      fields_set: Annotated[list, Field(default_factory=list)]
      dumped_fields_no_exclude: Annotated[dict, Field(default_factory=dict)]
      dumped_fields_exclude_default: Annotated[dict, Field(default_factory=dict)]
      dumped_fields_exclude_unset: Annotated[dict, Field(default_factory=dict)]
  
  
  
  app = FastAPI()
  
  
  @app.post("/form")
  async def form_endpoint(model: Annotated[ExampleFormModel, Form()]) -> ResponseSampleModel:
      return ResponseSampleModel(
          fields_set=list(model.model_fields_set),
          dumped_fields_no_exclude=model.model_dump(),
          dumped_fields_exclude_default=model.model_dump(exclude_defaults=True),
          dumped_fields_exclude_unset=model.model_dump(exclude_unset=True)
      )
  
  @app.post("/json")
  async def form_endpoint(model: ExampleJsonModel) -> ResponseSampleModel:
      return ResponseSampleModel(
          fields_set=list(model.model_fields_set),
          dumped_fields_no_exclude=model.model_dump(),
          dumped_fields_exclude_default=model.model_dump(exclude_defaults=True),
          dumped_fields_exclude_unset=model.model_dump(exclude_unset=True)
      )
  
  
  if __name__ == "__main__":
      uvicorn.run(app, host="0.0.0.0", port=8000)
  
  ```
  
  Test File: test_fastapi_defaults_bug.py
  ```python
  import pytest
  from fastapi.testclient import TestClient
  
  from fastapi_defaults_bug import (
      app,
      ExampleFormModel,
      ExampleJsonModel,
      ResponseSampleModel
  )
  
  @pytest.fixture(scope="module")
  def fastapi_client():
      with TestClient(app) as test_client:
          yield test_client
  
  
  ################
  # Section 1: Tests on Form model -> no fastapi, pydantic model
  ################
  
  def test_form_model_pydantic_only_defaults():
      f_model = ExampleFormModel()
      for field_name, field in f_model.model_fields.items():
          assert getattr(f_model, field_name) == field.default
  
  def test_form_model_pydantic_all_unset():
      f_model = ExampleFormModel()
      assert not f_model.model_fields_set
  
  def test_form_model_pydantic_set_1():
      f_model = ExampleFormModel(sample_field_1=True) # Those set have the same value of default
      assert "sample_field_1" in f_model.model_fields_set
      assert len(f_model.model_fields_set) == 1
  
  def test_form_model_pydantic_set_2():
      f_model = ExampleFormModel(sample_field_1=True, sample_field_2=False) # Those set have the same value of default
      assert "sample_field_1" in f_model.model_fields_set
      assert "sample_field_2" in f_model.model_fields_set
      assert len(f_model.model_fields_set) == 2
  
  def test_form_model_pydantic_set_all():
      f_model = ExampleFormModel(
          sample_field_1=True,
          sample_field_2=False,
          sample_field_3=True,
          sample_field_4=""
      ) # Those set could have different values from default
      assert not set(f_model.model_fields).difference(f_model.model_fields_set)
  
  ################
  # Section 2: Same Tests of Form on Json model -> they are the same on different model
  ################
  
  def test_json_model_pydantic_only_defaults():
      j_model = ExampleJsonModel()
      for field_name, field in j_model.model_fields.items():
          assert getattr(j_model, field_name) == field.default
  
  def test_json_model_pydantic_all_unset():
      j_model = ExampleJsonModel()
      assert not j_model.model_fields_set
  
  def test_json_model_pydantic_set_1():
      j_model = ExampleJsonModel(sample_field_1=True) # Those set have the same value of default
      assert "sample_field_1" in j_model.model_fields_set
      assert len(j_model.model_fields_set) == 1
  
  def test_json_model_pydantic_set_2():
      j_model = ExampleJsonModel(sample_field_1=True, sample_field_2=False) # Those set have the same value of default
      assert "sample_field_1" in j_model.model_fields_set
      assert "sample_field_2" in j_model.model_fields_set
      assert len(j_model.model_fields_set) == 2
  
  def test_json_model_pydantic_set_all():
      j_model = ExampleJsonModel(
          sample_field_1=True,
          sample_field_2=False,
          sample_field_3=True,
          sample_field_4=""
      ) # Those set could have different values from default
      assert not set(j_model.model_fields).difference(j_model.model_fields_set)
  
  def test_form_json_model_share_same_default_behaviour():
      f_model = ExampleFormModel()
      j_model = ExampleJsonModel()
  
      for field_name, field in f_model.model_fields.items():
          assert getattr(f_model, field_name) == getattr(j_model, field_name)
  
  
  ################
  # Section 3: Tests on Form model with fastapi
  ################
  
  
  def test_submit_form_with_all_values(fastapi_client: TestClient):
  
      form_content = {
          "sample_field_1": "False",
          "sample_field_2": "True",
          "sample_field_3": "False",
          "sample_field_4": "It's a random string"
      }
  
      response = fastapi_client.post("/form", data=form_content)
      assert response.status_code == 200
  
      response_model = ResponseSampleModel(**response.json())
      assert len(response_model.fields_set) == 4
      assert not set(form_content).symmetric_difference(set(response_model.fields_set))
  
  
  def test_submit_form_with_not_all_values(fastapi_client: TestClient):
      """
      This test should pass but fails because fastapi is preloading default and pass those values
      on model creation, losing the ability to know if a field has been set.
  
      :param fastapi_client:
      :return:
      """
  
      form_content = {
          "sample_field_1": "False",
          "sample_field_3": "False",
          "sample_field_4": "It's a random string"
      }
  
      response = fastapi_client.post("/form", data=form_content)
      assert response.status_code == 200
  
      response_model = ResponseSampleModel(**response.json())
      assert len(response_model.fields_set) == 3 # test will fail here and below
      assert not set(form_content).symmetric_difference(set(response_model.fields_set))
  
  
  def test_submit_form_with_no_values(fastapi_client: TestClient):
      """
      This test should pass but fails because fastapi is preloading default and pass those values
      on model creation, losing the ability to not have validation on default value.
  
      :param fastapi_client:
      :return:
      """
  
      form_content = {}
  
      response = fastapi_client.post("/form", data=form_content)
      assert response.status_code == 200 # test will fail here and below -> will raise 422
  
      response_model = ResponseSampleModel(**response.json())
      assert len(response_model.fields_set) == 0
      assert not set(form_content).symmetric_difference(set(response_model.fields_set))
  
  
  ################
  # Section 4: Tests on Json model with fastapi
  ################
  
  
  def test_submit_json_with_all_values(fastapi_client: TestClient):
  
      json_content = {
          "sample_field_1": False,
          "sample_field_2": True,
          "sample_field_3": False,
          "sample_field_4": "It's a random string"
      }
  
      response = fastapi_client.post("/json", json=json_content)
      assert response.status_code == 200
  
      response_model = ResponseSampleModel(**response.json())
      assert len(response_model.fields_set) == 4
      assert not set(json_content).symmetric_difference(set(response_model.fields_set))
  
  
  def test_submit_json_with_not_all_values(fastapi_client: TestClient):
      """
      This test will pass but the same not happen with Form.
  
      :param fastapi_client:
      :return:
      """
  
      json_content = {
          "sample_field_1": False,
          "sample_field_3": False,
          "sample_field_4": "It's a random string"
      }
  
      response = fastapi_client.post("/json", json=json_content)
      assert response.status_code == 200
  
      response_model = ResponseSampleModel(**response.json())
      assert len(response_model.fields_set) == 3 # This time will not fail
      assert not set(json_content).symmetric_difference(set(response_model.fields_set))
  
  
  def test_submit_json_with_no_values(fastapi_client: TestClient):
      """
       This test will pass but the same not happen with Form.
  
      :param fastapi_client:
      :return:
      """
  
      json_content = {}
  
      response = fastapi_client.post("/json", json=json_content)
      assert response.status_code == 200 # This time will not fail
  
      response_model = ResponseSampleModel(**response.json())
      assert len(response_model.fields_set) == 0
      assert not set(json_content).symmetric_difference(set(response_model.fields_set))
  
  ```
  
  
  ### Description
  
  This is a generalized version of the issue reported in https://github.com/fastapi/fastapi/discussions/13380 .
  This issue do not affect body json data.
  
  For models created from a form, during the parsing phase their default values are preloaded and passed to the validator to create the model. 
  1) This leads to a loss of information regarding which fields have been explicitly set, since default values are now considered as having been provided.
  12) Consequently, validation is enforced on default values, which might not be the intended behavior and anyway different from the one from json body.
  
  ### Operating System
  
  macOS - Linux
  
  ### Operating System Details
  
  _No response_
  
  ### FastAPI Version
  
  0.115.8
  
  ### Pydantic Version
  
  2.10.6
  
  ### Python Version
  
  Python 3.11 - Python 3.13.1