Browse Source

lint

pull/13464/head
sneakers-the-rat 3 months ago
parent
commit
3f2e0f572f
No known key found for this signature in database GPG Key ID: 6DCB96EF1E4D232D
  1. 4
      docs/en/docs/tutorial/request-form-models.md
  2. 8
      docs_src/request_form_models/tutorial003.py
  3. 10
      docs_src/request_form_models/tutorial003_an_py39.py
  4. 17
      docs_src/request_form_models/tutorial004.py
  5. 17
      docs_src/request_form_models/tutorial004_an_py39.py
  6. 15
      docs_src/request_form_models/tutorial004_pv1.py
  7. 15
      docs_src/request_form_models/tutorial004_pv1_an_py39.py
  8. 4
      fastapi/_compat.py

4
docs/en/docs/tutorial/request-form-models.md

@ -81,7 +81,7 @@ Say, for example, you were generating an HTML form from a model,
and that model had a boolean field in it that you wanted to display as a checkbox and that model had a boolean field in it that you wanted to display as a checkbox
with a default `True` value: with a default `True` value:
{* ../../docs_src/request_form_models/tutorial003_an_py39.py hl[10,18:22] *} {* ../../docs_src/request_form_models/tutorial003_an_py39.py hl[11,10:23] *}
This works as expected when the checkbox remains checked, This works as expected when the checkbox remains checked,
the form encoded data in the request looks like this: the form encoded data in the request looks like this:
@ -130,7 +130,7 @@ Validation context is a pydantic v2 only feature!
/// ///
{* ../../docs_src/request_form_models/tutorial004_an_py39.py hl[3,12:24] *} {* ../../docs_src/request_form_models/tutorial004_an_py39.py hl[7,13:25] *}
And with that, our form model should behave as expected when it is used with a form, And with that, our form model should behave as expected when it is used with a form,
JSON input, or elsewhere in the program! JSON input, or elsewhere in the program!

8
docs_src/request_form_models/tutorial003.py

@ -1,12 +1,14 @@
from pydantic import BaseModel
from fastapi import FastAPI, Form, Request from fastapi import FastAPI, Form, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from jinja2 import DictLoader, Environment from jinja2 import DictLoader, Environment
from pydantic import BaseModel
class MyModel(BaseModel): class MyModel(BaseModel):
checkbox: bool = True checkbox: bool = True
form_template = """ form_template = """
<form action="/form" method="POST"> <form action="/form" method="POST">
{% for field_name, field in model.model_fields.items() %} {% for field_name, field in model.model_fields.items() %}
@ -31,12 +33,14 @@ templates = Jinja2Templates(env=Environment(loader=loader))
app = FastAPI() app = FastAPI()
@app.get("/form", response_class=HTMLResponse) @app.get("/form", response_class=HTMLResponse)
async def show_form(request: Request): async def show_form(request: Request):
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, name="form.html", context={"model": MyModel} request=request, name="form.html", context={"model": MyModel}
) )
@app.post('/form')
@app.post("/form")
async def submit_form(data: MyModel = Form()) -> MyModel: async def submit_form(data: MyModel = Form()) -> MyModel:
return data return data

10
docs_src/request_form_models/tutorial003_an_py39.py

@ -1,14 +1,16 @@
from typing import Annotated from typing import Annotated
from pydantic import BaseModel
from fastapi import FastAPI, Form, Request from fastapi import FastAPI, Form, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from jinja2 import DictLoader, Environment from jinja2 import DictLoader, Environment
from pydantic import BaseModel
class MyModel(BaseModel): class MyModel(BaseModel):
checkbox: bool = True checkbox: bool = True
form_template = """ form_template = """
<form action="/form" method="POST"> <form action="/form" method="POST">
{% for field_name, field in model.model_fields.items() %} {% for field_name, field in model.model_fields.items() %}
@ -16,7 +18,7 @@ form_template = """
<label for="{{ field_name }}">{{ field_name }}</label> <label for="{{ field_name }}">{{ field_name }}</label>
{% if field.annotation.__name__ == "bool" %} {% if field.annotation.__name__ == "bool" %}
<input type="checkbox" name="{{field_name}}" <input type="checkbox" name="{{field_name}}"
{% if field.default %} {% if field.default %}
checked="checked" checked="checked"
{% endif %} {% endif %}
> >
@ -33,12 +35,14 @@ templates = Jinja2Templates(env=Environment(loader=loader))
app = FastAPI() app = FastAPI()
@app.get("/form", response_class=HTMLResponse) @app.get("/form", response_class=HTMLResponse)
async def show_form(request: Request): async def show_form(request: Request):
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, name="form.html", context={"model": MyModel} request=request, name="form.html", context={"model": MyModel}
) )
@app.post('/form')
@app.post("/form")
async def submit_form(data: Annotated[MyModel, Form()]) -> MyModel: async def submit_form(data: Annotated[MyModel, Form()]) -> MyModel:
return data return data

17
docs_src/request_form_models/tutorial004.py

@ -1,8 +1,9 @@
from pydantic import BaseModel, ValidationInfo, model_validator
from fastapi import FastAPI, Form, Request from fastapi import FastAPI, Form, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from jinja2 import DictLoader, Environment from jinja2 import DictLoader, Environment
from pydantic import BaseModel, ValidationInfo, model_validator
class MyModel(BaseModel): class MyModel(BaseModel):
checkbox: bool = True checkbox: bool = True
@ -10,15 +11,15 @@ class MyModel(BaseModel):
@model_validator(mode="before") @model_validator(mode="before")
def handle_defaults(cls, value: dict, info: ValidationInfo) -> dict: def handle_defaults(cls, value: dict, info: ValidationInfo) -> dict:
# if this model is being used outside of fastapi, return normally # if this model is being used outside of fastapi, return normally
if info.context is None or 'fastapi_field' not in info.context: if info.context is None or "fastapi_field" not in info.context:
return value return value
# check if we are being validated from form input, # check if we are being validated from form input,
# and if so, treat the unset checkbox as False # and if so, treat the unset checkbox as False
field_info = info.context['fastapi_field'].field_info field_info = info.context["fastapi_field"].field_info
is_form = type(field_info).__name__ == "Form" is_form = type(field_info).__name__ == "Form"
if is_form and 'checkbox' not in value: if is_form and "checkbox" not in value:
value['checkbox'] = False value["checkbox"] = False
return value return value
@ -29,7 +30,7 @@ form_template = """
<label for="{{ field_name }}">{{ field_name }}</label> <label for="{{ field_name }}">{{ field_name }}</label>
{% if field.annotation.__name__ == "bool" %} {% if field.annotation.__name__ == "bool" %}
<input type="checkbox" name="{{field_name}}" <input type="checkbox" name="{{field_name}}"
{% if field.default %} {% if field.default %}
checked="checked" checked="checked"
{% endif %} {% endif %}
> >
@ -46,12 +47,14 @@ templates = Jinja2Templates(env=Environment(loader=loader))
app = FastAPI() app = FastAPI()
@app.get("/form", response_class=HTMLResponse) @app.get("/form", response_class=HTMLResponse)
async def show_form(request: Request): async def show_form(request: Request):
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, name="form.html", context={"model": MyModel} request=request, name="form.html", context={"model": MyModel}
) )
@app.post('/form')
@app.post("/form")
async def submit_form(data: MyModel = Form()) -> MyModel: async def submit_form(data: MyModel = Form()) -> MyModel:
return data return data

17
docs_src/request_form_models/tutorial004_an_py39.py

@ -1,10 +1,11 @@
from typing import Annotated from typing import Annotated
from pydantic import BaseModel, ValidationInfo, model_validator
from fastapi import FastAPI, Form, Request from fastapi import FastAPI, Form, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from jinja2 import DictLoader, Environment from jinja2 import DictLoader, Environment
from pydantic import BaseModel, ValidationInfo, model_validator
class MyModel(BaseModel): class MyModel(BaseModel):
checkbox: bool = True checkbox: bool = True
@ -12,15 +13,15 @@ class MyModel(BaseModel):
@model_validator(mode="before") @model_validator(mode="before")
def handle_defaults(cls, value: dict, info: ValidationInfo) -> dict: def handle_defaults(cls, value: dict, info: ValidationInfo) -> dict:
# if this model is being used outside of fastapi, return normally # if this model is being used outside of fastapi, return normally
if info.context is None or 'fastapi_field' not in info.context: if info.context is None or "fastapi_field" not in info.context:
return value return value
# check if we are being validated from form input, # check if we are being validated from form input,
# and if so, treat the unset checkbox as False # and if so, treat the unset checkbox as False
field_info = info.context['fastapi_field'].field_info field_info = info.context["fastapi_field"].field_info
is_form = type(field_info).__name__ == "Form" is_form = type(field_info).__name__ == "Form"
if is_form and 'checkbox' not in value: if is_form and "checkbox" not in value:
value['checkbox'] = False value["checkbox"] = False
return value return value
@ -31,7 +32,7 @@ form_template = """
<label for="{{ field_name }}">{{ field_name }}</label> <label for="{{ field_name }}">{{ field_name }}</label>
{% if field.annotation.__name__ == "bool" %} {% if field.annotation.__name__ == "bool" %}
<input type="checkbox" name="{{field_name}}" <input type="checkbox" name="{{field_name}}"
{% if field.default %} {% if field.default %}
checked="checked" checked="checked"
{% endif %} {% endif %}
> >
@ -48,12 +49,14 @@ templates = Jinja2Templates(env=Environment(loader=loader))
app = FastAPI() app = FastAPI()
@app.get("/form", response_class=HTMLResponse) @app.get("/form", response_class=HTMLResponse)
async def show_form(request: Request): async def show_form(request: Request):
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, name="form.html", context={"model": MyModel} request=request, name="form.html", context={"model": MyModel}
) )
@app.post('/form')
@app.post("/form")
async def submit_form(data: Annotated[MyModel, Form()]) -> MyModel: async def submit_form(data: Annotated[MyModel, Form()]) -> MyModel:
return data return data

15
docs_src/request_form_models/tutorial004_pv1.py

@ -1,18 +1,19 @@
from pydantic import BaseModel, model_validator
from fastapi import FastAPI, Form, Request from fastapi import FastAPI, Form, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from jinja2 import DictLoader, Environment from jinja2 import DictLoader, Environment
from pydantic import BaseModel, root_validator
class MyModel(BaseModel): class MyModel(BaseModel):
checkbox: bool = True checkbox: bool = True
@model_validator(mode="before") @root_validator(pre=True)
def handle_defaults(cls, value: dict) -> dict: def handle_defaults(cls, value: dict) -> dict:
# We can't tell if we're being validated by fastAPI, # We can't tell if we're being validated by fastAPI,
# so we have to just YOLO this. # so we have to just YOLO this.
if 'checkbox' not in value: if "checkbox" not in value:
value['checkbox'] = False value["checkbox"] = False
return value return value
@ -23,7 +24,7 @@ form_template = """
<label for="{{ field_name }}">{{ field_name }}</label> <label for="{{ field_name }}">{{ field_name }}</label>
{% if field.annotation.__name__ == "bool" %} {% if field.annotation.__name__ == "bool" %}
<input type="checkbox" name="{{field_name}}" <input type="checkbox" name="{{field_name}}"
{% if field.default %} {% if field.default %}
checked="checked" checked="checked"
{% endif %} {% endif %}
> >
@ -40,12 +41,14 @@ templates = Jinja2Templates(env=Environment(loader=loader))
app = FastAPI() app = FastAPI()
@app.get("/form", response_class=HTMLResponse) @app.get("/form", response_class=HTMLResponse)
async def show_form(request: Request): async def show_form(request: Request):
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, name="form.html", context={"model": MyModel} request=request, name="form.html", context={"model": MyModel}
) )
@app.post('/form')
@app.post("/form")
async def submit_form(data: MyModel = Form()) -> MyModel: async def submit_form(data: MyModel = Form()) -> MyModel:
return data return data

15
docs_src/request_form_models/tutorial004_pv1_an_py39.py

@ -1,20 +1,21 @@
from typing import Annotated from typing import Annotated
from pydantic import BaseModel, model_validator
from fastapi import FastAPI, Form, Request from fastapi import FastAPI, Form, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from jinja2 import DictLoader, Environment from jinja2 import DictLoader, Environment
from pydantic import BaseModel, root_validator
class MyModel(BaseModel): class MyModel(BaseModel):
checkbox: bool = True checkbox: bool = True
@model_validator(mode="before") @root_validator(pre=True)
def handle_defaults(cls, value: dict) -> dict: def handle_defaults(cls, value: dict) -> dict:
# We can't tell if we're being validated by fastAPI, # We can't tell if we're being validated by fastAPI,
# so we have to just YOLO this. # so we have to just YOLO this.
if 'checkbox' not in value: if "checkbox" not in value:
value['checkbox'] = False value["checkbox"] = False
return value return value
@ -25,7 +26,7 @@ form_template = """
<label for="{{ field_name }}">{{ field_name }}</label> <label for="{{ field_name }}">{{ field_name }}</label>
{% if field.annotation.__name__ == "bool" %} {% if field.annotation.__name__ == "bool" %}
<input type="checkbox" name="{{field_name}}" <input type="checkbox" name="{{field_name}}"
{% if field.default %} {% if field.default %}
checked="checked" checked="checked"
{% endif %} {% endif %}
> >
@ -42,12 +43,14 @@ templates = Jinja2Templates(env=Environment(loader=loader))
app = FastAPI() app = FastAPI()
@app.get("/form", response_class=HTMLResponse) @app.get("/form", response_class=HTMLResponse)
async def show_form(request: Request): async def show_form(request: Request):
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, name="form.html", context={"model": MyModel} request=request, name="form.html", context={"model": MyModel}
) )
@app.post('/form')
@app.post("/form")
async def submit_form(data: Annotated[MyModel, Form()]) -> MyModel: async def submit_form(data: Annotated[MyModel, Form()]) -> MyModel:
return data return data

4
fastapi/_compat.py

@ -126,7 +126,9 @@ if PYDANTIC_V2:
) -> Tuple[Any, Union[List[Dict[str, Any]], None]]: ) -> Tuple[Any, Union[List[Dict[str, Any]], None]]:
try: try:
return ( return (
self._type_adapter.validate_python(value, from_attributes=True, context={"fastapi_field": self}), self._type_adapter.validate_python(
value, from_attributes=True, context={"fastapi_field": self}
),
None, None,
) )
except ValidationError as exc: except ValidationError as exc:

Loading…
Cancel
Save