tiangolo / fastapi Goto Github PK
View Code? Open in Web Editor NEWFastAPI framework, high performance, easy to learn, fast to code, ready for production
Home Page: https://fastapi.tiangolo.com/
License: MIT License
FastAPI framework, high performance, easy to learn, fast to code, ready for production
Home Page: https://fastapi.tiangolo.com/
License: MIT License
Hi there!
First of all, gerat project! Thank You for sharing it!
i'm a somewhat a beginner, i'd like some help if you guys don't mind. (I couldn't find another forum for questions)
I've managed to read a list of objects inside a json, by passing the body like this:
[
{
"name": "Item name example 1",
"price": 100,
"is_offer": true
},
{
"name": "Item name example 2",
"price": 100,
"is_offer": true
},
{
"name": "Item name example 3",
"price": 100,
"is_offer": true
}
]
The objective of my micro example is to receive a list of Items (the same base class of the API example), do some processing (change price value by a fixed factor) and return that altered list.
this works:
@app.put("/items/{item_id}")
def create_item(item_id: int, items: List[Item]):
return {"total" : len(items)}
and i can iterate trough the list with
for item in items:
but when i try to return the list with
return {items}
i get "TypeError: unhashable type: 'list'" error.
is there a simple way to return the list? Or i'll need to create the return string manually?
Documentation states that FastAPI has support for WebSockets but there is no example on how to deal with it in code. Search on the internet is giving no results.
Description
I need to support several query parameters with same name in GET route. Typical request looks like this:
http://localhost/item?num=1&num=2
I configured a route
@app.get("/item", content_type=UJSONResponse)
async def get_part(num: list):
found = False
for i in num:
if i in some_data:
found = True
break
return {"found": found}
The idea is, that I can pass several numbers to check, if they exist in some_data. In my opinion, it is not a good idea to get numbers from body here, because it is a simple GET request, but in current version application expects argument "num" in body, so on my request (written above) I receive a response
{"detail":[{"loc":["body","num"],"msg":"field required","type":"value_error.missing"}]}
As I know, it is not restricted to pass several query parameters with the same name in an HTTP request by any specifications, so I would like to ask, is it possible to configure a route in FastAPI, which will be able to parse several query parameters with the same name?
In starlette you can access request object in function decorated with the route decorator.
it seems very handy to be able to access middlewares etc,
is there a way in fastapi to do that using the provided get/post/options.... decorators?
same question for the ApiRouter.
@app.route("/notes", methods=["GET"])
async def list_notes(request):
query = notes.select()
results = await request.database.fetchall(query)
Description
How can I [...]? I'm using structlog for logging in the application to get JSON logs (for loading into centralized logging service). The FastAPI/Starlette?/uvicorn logging is using standard text-based logging. What is the best way to override that to use my structlog configuration?
Additional context
Here is my structlog setup if that is useful:
import sys
import logging
import structlog
import structlog._frames
def logging_setup(settings):
log_level = settings.LOGGING
logging.basicConfig(format="%(message)s", stream=sys.stdout, level=log_level)
logger = logging.getLogger()
logger.setLevel(log_level)
def add_app_context(logger, method_name, event_dict):
f, name = structlog._frames._find_first_app_frame_and_name(["logging", __name__])
event_dict["file"] = f.f_code.co_filename
event_dict["line"] = f.f_lineno
event_dict["function"] = f.f_code.co_name
return event_dict
structlog.configure(
logger_factory=structlog.stdlib.LoggerFactory(),
processors=[
structlog.stdlib.filter_by_level,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
add_app_context,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.JSONRenderer(indent=2, sort_keys=True),
],
)
I'm getting a mix of logging results:
pynanopubstore | Checking for script in /app/prestart.sh
pynanopubstore | There is no script /app/prestart.sh
pynanopubstore | INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
pynanopubstore | INFO: Started reloader process [1]
pynanopubstore | 2019-03-12 19:05.17 Using config file: None
pynanopubstore | HEAD http://dev.biodati.test:9200/nanopubstore [status:200 request:0.006s]
pynanopubstore | Started server process [9]
pynanopubstore | Waiting for application startup.
pynanopubstore | ('172.18.0.5', 32940) - "GET /docs HTTP/1.1" 200
pynanopubstore | ('172.18.0.5', 32940) - "GET /openapi.json HTTP/1.1" 200
pynanopubstore | {
pynanopubstore | "doc_type": "nanopub",
pynanopubstore | "event": "will do ES search",
pynanopubstore | "file": "./services/search.py",
pynanopubstore | "from_": 0,
pynanopubstore | "function": "es_search",
pynanopubstore | "index": "nanopubstore",
pynanopubstore | "level": "info",
pynanopubstore | "line": 247,
pynanopubstore | "logger": "services.search",
pynanopubstore | "query": {
pynanopubstore | "query_string": {
pynanopubstore | "allow_leading_wildcard": true,
pynanopubstore | "default_field": "*",
pynanopubstore | "query": "this OR that"
pynanopubstore | }
pynanopubstore | },
pynanopubstore | "size": 50,
pynanopubstore | "timestamp": "2019-03-12T19:05:26.385863Z"
pynanopubstore | }
pynanopubstore | POST http://dev.biodati.test:9200/nanopubstore/nanopub/_search?size=50&from=0 [status:200 request:0.393s]
pynanopubstore | ('172.18.0.5', 32940) - "POST /search HTTP/1.1" 200
uvicorn
from the console.Changes you'll want to make:
Switch the docs to uvicorn --reload
instead of uvicorn --debug
.
Debug tracebacks will be becoming strictly an application-level concern, and will disappear from uvicorn in a future version. If you want debug tracebacks, make sure you're using starlette's ServerErrorMiddleware, and switching it on or off appropriately depending on if FastAPI is running in a debug mode or not.
Description
What is the best way to handle users registers, login, pasword changes, unregister?
A way to manage permissions and roles?
Additional context
Something similar to flask-auth , flask -security, flask login?
First of all, amazing project @tiangolo !
I have a quick question. I want the request body example in the Swagger UI documentation to represent some API calls the user would want to make. However, all I can see are the default values I have set in the BaseModel like "string" (see image). How do I change the examples in the documentation without changing the BaseModel? E.g. I wan't an user using the API to get another default value than the value you see in the Swagger documentation.
How can the scope parameter of the Security object be accessed?
Security accepts scopes as a parameter but the callable doesn't seem to be able to access it. The use case is essentially what is mentioned in the documentation - require certain scopes to be present to access an endpoint, or generate a 403 error.
What if you don't need the security parameter in the callback?
In the above use case, I'd like to require one of a set of scopes to be present but which one isn't really important. Using Security requires that a parameter be added like:
arg = Security(<callable>)
In callable(), test for the scopes and throw an HTTPException as needed. The problem is that arg isn't needed, so its ugly to pass it to the function. A much cleaner implementation would be to use a decorator - similar to the Starlette requires - like:
@requires(["user:read", "admin"])
Is this possible with the FastAPI design? If so, how does the decorate get passed a list of scopes (from the request)?
I am working with this example in the documentation that shows a basic example of how to work with files.
Is it possible to stream a large file with this? What is the correct pattern?
It's possible to stream files with starlette, so how would integrating this functionality with fastapi work?
Thank you!
Uvicorn is a great and fast HTTP/1 ASGI server that you recommend. I propose you recommend Hypercorn as a fast HTTP/2 ASGI server.
I'm the Hypercorn author, so naturally very biased. Also congratulations on the recognition of your great work.
It would be useful to show how to accomplish integrating fastapi with graphene or another graphQL interface. Its touched on lightly in the docs, but I couldn't find a complete example that reuses the good parts of fastapi and pydantic.
Is this too far out of scope for a suggestion?
Hi,
First of all, thank you for all the amazing work you've done with FastAPI. I'm just scratching the surface and I'm already amazed by what you're able to do right out of the box.
As for my question, At my institute we use a centralized authentication service for all webapps base on ORY Hydra. Is there an easy way built in to integrate an external server to authenticate again and use the token query the API?
Thanks
M
Describe the bug
The jsonable_encoder crashes rightfully when passing a list of postgres Records, it's certainly a mis usage on my end, but I think that is something that would be interesting maybe to add in that function
Connected to pydev debugger (build 183.5429.31)
backend_1_f0c43d42b730 | WARNING:root:email-validator not installed, email fields will be treated as str.
backend_1_f0c43d42b730 | To install, run: pip install email-validator
backend_1_f0c43d42b730 | DEBUG:app.app:postgresql://postgres:postgres@db:5432/fastapi_dev
backend_1_f0c43d42b730 | INFO:uvicorn:Started server process [1]
backend_1_f0c43d42b730 | INFO:uvicorn:Waiting for application startup.
backend_1_f0c43d42b730 | INFO:uvicorn:Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
backend_1_f0c43d42b730 | Traceback (most recent call last):
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 78, in jsonable_encoder
backend_1_f0c43d42b730 | encoder = ENCODERS_BY_TYPE[type(obj)]
backend_1_f0c43d42b730 | KeyError: <class 'sqlalchemy.sql.base.ColumnCollection'>
backend_1_f0c43d42b730 |
backend_1_f0c43d42b730 | During handling of the above exception, another exception occurred:
backend_1_f0c43d42b730 |
backend_1_f0c43d42b730 | Traceback (most recent call last):
backend_1_f0c43d42b730 | File "/opt/.pycharm_helpers/pydev/_pydevd_bundle/pydevd_trace_dispatch_regular.py", line 145, in __call__
backend_1_f0c43d42b730 | if not is_stepping and cache_key in cache_skips:
backend_1_f0c43d42b730 | RecursionError: maximum recursion depth exceeded in comparison
backend_1_f0c43d42b730 | Fatal Python error: Cannot recover from stack overflow.
backend_1_f0c43d42b730 |
backend_1_f0c43d42b730 | Thread 0x00007f5d9ffa9ae8 (most recent call first):
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 300 in wait
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 552 in wait
backend_1_f0c43d42b730 | File "/opt/.pycharm_helpers/pydev/pydevd.py", line 128 in _on_run
backend_1_f0c43d42b730 | File "/opt/.pycharm_helpers/pydev/_pydevd_bundle/pydevd_comm.py", line 320 in run
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 917 in _bootstrap_inner
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 885 in _bootstrap
backend_1_f0c43d42b730 |
backend_1_f0c43d42b730 | Thread 0x00007f5da00acae8 (most recent call first):
backend_1_f0c43d42b730 | File "/opt/.pycharm_helpers/pydev/_pydevd_bundle/pydevd_comm.py", line 382 in _on_run
backend_1_f0c43d42b730 | File "/opt/.pycharm_helpers/pydev/_pydevd_bundle/pydevd_comm.py", line 320 in run
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 917 in _bootstrap_inner
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 885 in _bootstrap
backend_1_f0c43d42b730 |
backend_1_f0c43d42b730 | Thread 0x00007f5da01afae8 (most recent call first):
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 300 in wait
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/queue.py", line 179 in get
backend_1_f0c43d42b730 | File "/opt/.pycharm_helpers/pydev/_pydevd_bundle/pydevd_comm.py", line 459 in _on_run
backend_1_f0c43d42b730 | File "/opt/.pycharm_helpers/pydev/_pydevd_bundle/pydevd_comm.py", line 320 in run
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 917 in _bootstrap_inner
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/threading.py", line 885 in _bootstrap
backend_1_f0c43d42b730 |
backend_1_f0c43d42b730 | Current thread 0x00007f5da6097b88 (most recent call first):
backend_1_f0c43d42b730 | File "/opt/.pycharm_helpers/pydev/_pydevd_bundle/pydevd_trace_dispatch_regular.py", line 145 in __call__
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/operators.py", line 425 in __getitem__
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 707 in operate
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/operators.py", line 432 in __getitem__
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 83 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 96 in jsonable_encoder
backend_1_f0c43d42b730 | File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 54 in jsonable_encoder
backend_1_f0c43d42b730 | ...
fastapi_appfactory_backend_1_f0c43d42b730 exited with code 139
Aborting on container exit...
To Reproduce
Here's my simple app, I want to test the databases package from starlette
import logging
from typing import List
from fastapi import FastAPI
from app import settings
from app.settings import database
from app.models import notes, NoteIn
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.debug(settings.DATABASE_URL)
app = FastAPI()
app.debug = settings.DEBUG
@app.on_event("startup")
async def startup():
await database.connect()
@app.on_event("shutdown")
async def shutdown():
await database.disconnect()
@app.get("/")
async def root():
logger.debug(database)
return {"message": "Hello World"}
@app.get("/notes", response_model=List[NoteIn])
async def list_notes():
query = notes.select()
results = await database.fetch_all(query)
# content = [
# {"text": result["text"], "completed": result["completed"]} for result in results
# ]
# return content
return results
@app.post("/notes")
async def add_note(note: NoteIn):
query = notes.insert().values(**note.dict())
await database.execute(query)
return note
Should you want I may give you the full gitlab repo address that can reproduce it simply with a docker-compose, instead of copying all files :)
Expected behavior
If I return content instead of results in the list_notes
route I got no problem, so that one workaround.
Another workaround is to return
return [r._row for r in results]
but i don't like much using private attributes
I got the feeling that results
, being a list of databases.backends.postgres.Record
it might be rightfully "parsed" by jsonable_encoder
by adding another if isinstance(obj, blablabla):
check
So maybe not a bug, but a possible enhancement ;)
when using DatabaseMiddleware, the fetchall method (note, no underscore in it) return a list of asyncpg.Records
which the encoder parsed fine: results = await request.database.fetchall(query)
now we got a list of databases.backends.postgres.Record
Environment:
import fastapi
print(fastapi.__version__)
python --version
Additional context
Add any other context about the problem here.
Depends()
works great, but does not support post-response cleanup. How about injecting from context managers? Taking the SQL Db example, it would not need middleware anymore:
from contextlib import contextmanager
@contextmanager
def db() -> Session:
db_session = Session()
try:
yield db_session
finally:
db_session.close()
@app.get("/users/{user_id}")
def read_user(user_id: int, db_session: Session = Depends(db)):
user = get_user(db_session, user_id=user_id)
return user
Middlewares do the job and they have been there forever, but from the FastAPI idiomatic approach request.scope
looks a bit of a "dumpster" - it's not known in advance what to expect there without examining middlware docs/code. Middlewares also need to take care not to step on each other. And finally, not all paths may need that request.scope.db
. By supporting contextmanager injection, I believe code can be more idiomatic, and more efficient (e.g. because we'll only initialize Session()
for requests that need it).
What do you think?
Implementation wise, I guess dependencies.utils.solve_dependencies
needs to return ctxmgrs
in addition to values
and errors
. Then during execution we can use either contextlib.ExitStack
or contextlib.AsyncExitStack
(the latter is Python 3.7 only though) to wrap the execution with.
Also, since a "thing" passed to Depends()
can be both callable and context manager, may be it worth having new DependsContextMgr()
class. And finally, I think there should be some type checking to make sure that only async context managers are injected into async request handlers and vise-versa.
I can work on a PR for this if the initiative is going to be accepted.
In order to deploy the 'bigger application' as outlined here:
https://fastapi.tiangolo.com/tutorial/bigger-applications/
One must modify the Dockerfile:
https://fastapi.tiangolo.com/deployment/#build-your-image
to:
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
COPY ./app /app/app
This way the relative imports work correctly as the $PYTHONPATH
is /app
.
Thanks again for an awesome project! Been loving it so far.
Does FastAPI support Swagger (OpenAPI) version 2.0 or just 3.0 of the spec?
For example, https://bravado.readthedocs.io/en/stable/, supports only version 2.0.
Hello
I've seen on FastAPI documentation site, that it integrates nice with a VSCode.
Any hint on debugging an FastAPI application in VSCode? There are some exaple configrations for python projects, but unfortunately I'm not able to utilize these for FastAPI
Thanks
Olegas
Is your feature request related to a problem? Please describe.
In order to rapid development, A crud generator (front end) would be great.
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
It can be documentation about generating basic crud.
Additional context
I'm not sure wether this is within the framework scope, but I just want to get flask behind.
This, and user/permission management are maybe the only 2 things lacking. IMHO.
Hello there,
First, I have to say that I am really impressed by what you guys are doing here. Also, your docs are outstanding and easy to follow. I spotted your project on my recommendations page and immediately fell in love, losing most of my Friday night tinkering around.
When I got to your file upload section in the docs, I hit a snag when trying to upload an mp4 file.
{ "detail": [ { "loc": [ "body", "file" ], "msg": "ensure this value has at most 65536 characters", "type": "value_error.any_str.max_length", "ctx": { "limit_value": 65536 } } ] }
It seems like the File type expects bytes as strings, which aren't allowed to go past 65536 characters in length. I expect others might run into this too, or be confused like I am when hitting this part.
-Russell
Is your feature request related to a problem? Please describe.
If we use the following option with sub-routes
app.include_router(search_router, prefix="/items")
We are forced to have an ending '/' on the collection endpoints, e.g. /items/ vs /items/{id} This is I think the more formal REST practice, but it results in a 404 when someone uses /items instead - I'd rather follow the mantra of 'be flexible with regards to user input and strict with what I return'. I'd like to have the option of allowing both /items and /items/ for the collection endpoints.
Describe the solution you'd like
I'd be happier to have a single route documented and the other route just work. I do like the setup of the prefixing of sub-routes - that's really convenient and powerful. But, I need to have the /items collection route option which prefix'ing doesn't allow for.
Describe alternatives you've considered
I can provide an /items endpoint without using the prefix option. I don't know if there is a better way to handle this though. I also managed to add two route decorators to get both /items and /items/ working as endpoints and documented in Swagger - unfortunately Swagger doesn't support synonymous routes yet. I'd be happier to have a single route documented and the other route just work.
Additional context
API that I'm implementing requires from me input and output in camel case style. But I want to use snake case in my python code and follow pep8. So I tried allow_population_by_alias
in my config class from the pydantic model and it works as expected without fastapi. But in fastapi, I can get the right response only when I set by_alias
in jsonable_encoder
to true. Is it possible to use this argument somehow from route decorators? I know that pydantic docs says that it's bad practice to use allow_population_by_alias
, but I don't know another way to implement the specification as I want. The best way will be to have in fastapi or pydantic decorator for auto-renaming fields like this in serde for rust, but it's not important for me now. I just want my code to pass these tests now:
import json
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel, Schema
import pytest
from starlette.testclient import TestClient
app = FastAPI()
class Model(BaseModel):
model_field: str = Schema(..., alias="modelField")
class Config:
allow_population_by_alias = True
@app.get("/models", response_model=List[Model])
def get_models():
m = Model(model_field="string")
return [
Model(model_field=m.model_field),
Model(modelField=m.model_field),
Model(**m.dict()),
Model(**m.dict(by_alias=True)),
]
@app.post("/models", response_model=Model)
def create_model(m: Model):
return Model(**m.dict())
@pytest.fixture
def client():
yield TestClient(app)
def test_get_models(client):
with client:
response = client.get("/models")
assert response.json() == [{"modelField": "string"} for _ in range(4)]
def test_create_model(client):
with client:
response = client.post("/models", json.dumps({"modelField": "string"}))
assert response.json() == {"modelField": "string"}
Hope this is the right place for a question.
I have a REST API post request that does a lot of computation, /crunch
. Rather than block the event loop I would like /crunch
to return 202 Accepted
status code along with a token string. Then the user of the API can call get request /result/{token}
to check on the status of the computation. This is outlined nicely here for example.
Is it possible to modify the response status code, for example, similar to this approach in Sanic?
Hello,
First, thanks for all your docker project generators as well as the fantastic documentation. They have been super useful in getting my project off the ground.
I've been following the sqlalchemy example at: https://fastapi.tiangolo.com/tutorial/sql-databases/.
I'm trying to return a sqlalchemy data model, but I am getting the following error:
Fatal Python error: Cannot recover from stack overflow.
Thread 0x00007f115f510700 (most recent call first):
File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker
File "/usr/local/lib/python3.7/threading.py", line 865 in run
File "/usr/local/lib/python3.7/threading.py", line 917 in _bootstrap_inner
File "/usr/local/lib/python3.7/threading.py", line 885 in _bootstrap
Current thread 0x00007f116c905700 (most recent call first):
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 834 in __getattr__
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 836 in __getattr__
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/attributes.py", line 190 in __getattr__
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 51 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 30 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 59 in jsonable_encoder
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 31 in <dictcomp>
...
INFO: Stopping reloader process [2468]
If I modify the fastapi specific code:
https://fastapi.tiangolo.com/tutorial/sql-databases/#create-your-fastapi-code
and parse the sqlalchemy response into a dictionary, it works fine:
@app.get("/users/{username}")
def read_user(username: str):
user = get_user(username, db_session)
user = {"name": user.id, "email": user.email}
return user
Thanks again. Been loving FastAPI so far.
The docs are currently broken and I was so far unable to fix it using the docs at: https://fastapi.tiangolo.com/tutorial/application-configuration/
Is this a known issue or am I doing something wrong?
Description
How can I [...]?
I'm trying to figure out how to use one endpoint for multiple response content_types? I want to create an /export API endpoint and be able to dump (from memory) responses such as application/json, application/yaml or application/zip based on the content-type requested.
Everything I've seen so far is just for a single response type - though I've probably missed something because this is one of the best documented projects I've used.
Starlette has the notion of custom error handlers that look like routes, which are invoked when an HTTPException
is raised inside a regular route. Is this a thing that can be done in FastAPI?
Related documentation:
Describe the bug
I have a pydantic schema that needs a third party class (bson.objectid.ObjectID) as a property. For this reason I created a custom validator and encoder as per pydantic documentation.
from bson.objectid import ObjectId
from pydantic import BaseModel
from pydantic import validators
from pydantic.errors import PydanticTypeError
from pydantic.utils import change_exception
class ObjectIdError(PydanticTypeError):
msg_template = 'value is not a valid bson.objectid.ObjectId'
def object_id_validator(v) -> ObjectId:
with change_exception(ObjectIdError, ValueError):
v = ObjectId(v)
return v
def get_validators() -> None:
yield validators.not_none_validator
yield object_id_validator
ObjectId.__get_validators__ = get_validators
def encode_object_id(object_id: ObjectId):
return str(object_id)
class UserId(BaseModel):
object_id: ObjectId = None
class Config:
json_encoders = {
ObjectId: encode_object_id
}
class User(UserId):
email: str
salt: str
hashed_password: str
# Just for testing
user = User(object_id = ObjectId(), email="[email protected]", salt="12345678", hashed_password="letmein")
print(user.json())
# Outputs:
# {"object_id": "5c7e424225e2971c8c548a86", "email": "[email protected]", "salt": "12345678", "hashed_password": "letmein"}
As you can see at the bottom of the code, the serialization seems to work just fine. But when I use this schema as an argument (and/or response type) in API operations and then open the automatic documentation, I get presented with an error.
from bson import ObjectId
from fastapi import FastAPI
from user import User, UserId
app = FastAPI()
@app.post("/user", tags=["user"], response_model=UserId)
def create_user(user: User):
# Create user and return id
print(user)
return UserId(objectId=ObjectId())
INFO: ('127.0.0.1', 2706) - "GET /openapi.json HTTP/1.1" 500
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "<project-path>\venv\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 373, in run_asgi
result = await asgi(self.receive, self.send)
File "<project-path>\venv\lib\site-packages\uvicorn\middleware\debug.py", line 83, in __call__
raise exc from None
File "<project-path>\venv\lib\site-packages\uvicorn\middleware\debug.py", line 80, in __call__
await asgi(receive, self.send)
File "<project-path>\venv\lib\site-packages\starlette\middleware\errors.py", line 125, in asgi
raise exc from None
File "<project-path>\venv\lib\site-packages\starlette\middleware\errors.py", line 103, in asgi
await asgi(receive, _send)
File "<project-path>\venv\lib\site-packages\starlette\exceptions.py", line 74, in app
raise exc from None
File "<project-path>\venv\lib\site-packages\starlette\exceptions.py", line 63, in app
await instance(receive, sender)
File "<project-path>\venv\lib\site-packages\starlette\routing.py", line 43, in awaitable
response = await run_in_threadpool(func, request)
File "<project-path>\venv\lib\site-packages\starlette\concurrency.py", line 24, in run_in_threadpool
return await loop.run_in_executor(None, func, *args)
File "C:\Program Files (x86)\Python37-32\lib\concurrent\futures\thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "<project-path>\venv\lib\site-packages\fastapi\applications.py", line 83, in <lambda>
lambda req: JSONResponse(self.openapi()),
File "<project-path>\venv\lib\site-packages\fastapi\applications.py", line 75, in openapi
openapi_prefix=self.openapi_prefix,
File "<project-path>\venv\lib\site-packages\fastapi\openapi\utils.py", line 230, in get_openapi
flat_models=flat_models, model_name_map=model_name_map
File "<project-path>\venv\lib\site-packages\fastapi\utils.py", line 45, in get_model_definitions
model, model_name_map=model_name_map, ref_prefix=REF_PREFIX
File "<project-path>\venv\lib\site-packages\pydantic\schema.py", line 461, in model_process_schema
model, by_alias=by_alias, model_name_map=model_name_map, ref_prefix=ref_prefix
File "<project-path>\venv\lib\site-packages\pydantic\schema.py", line 482, in model_type_schema
f, by_alias=by_alias, model_name_map=model_name_map, ref_prefix=ref_prefix
File "<project-path>\venv\lib\site-packages\pydantic\schema.py", line 238, in field_schema
ref_prefix=ref_prefix,
File "<project-path>\venv\lib\site-packages\pydantic\schema.py", line 440, in field_type_schema
ref_prefix=ref_prefix,
File "<project-path>\venv\lib\site-packages\pydantic\schema.py", line 643, in field_singleton_schema
raise ValueError(f'Value not declarable with JSON Schema, field: {field}')
ValueError: Value not declarable with JSON Schema, field: object_id type=ObjectId default=None
To Reproduce
Copy my code and follow the instrcutions given in the "Describe the bug" section.
Expected behavior
No error should occur and the documentation should be able to show the schema correctly.
Environment:
starlette 0.9.11 breaks fastapi routing
I'm currently working around this by enforcing starlette==0.9.10
How do we add additional responses (e.g. 401, 403, 500, etc..) to the documentation other than the default 200 response and the 422 validation error response?
Description
How can I use peewee ORM with fastapi?
Additional context
I'd love to use peewee rather than sqlalchemy for my API. However, all documentation seems to be oriented to SQLAlchemy.
It seems like I can use peewee directly up to a certain point, however some stuff (like ForeignKey relations) don't really work by default.
Starlette allows to attach a list of background tasks to a response, that will run only once the response has been sent.
If the task is a not a coroutine is it executed on a specific executor to not block the event loop.
if task.is_coroutine():
future = asyncio.ensure_future(task())
else:
loop = asyncio.get_event_loop()
future = await loop.run_in_executor(None, task.func)
Is there any possibility to add this great feature to Fastai ?
I want the user to be able to select parameter values from an enum list of values as a dropdown in the swagger documentation.
The only way, to my knowledge, to do that is to create a Enum pydantic class, and designate a parameter as a part of that class. Which is fine. But in my situation, I want the enum to be dynamically generated based on all unique document values of a property stored in a MongoDB collection. I think you can create a BaseModel class dynamically using the create_model() function, but as far as I know that's not possible with a Enum class.
So my question is: How can I create a parameter enumeration in Swagger from all values in a mongDb collection?
Description
In Flask, I've found this to be a common pattern to do something like this:
run_app.py
from api.factory import create_app
app = create_app()
api/factory.py
from flask import Flask, current_app
import redis
import config
from api.resources.basic import basic
def create_app():
"""Create the app."""
app = Flask(__name__)
app.config.from_object(config.ProductionConfig)
app.redis = redis.Redis(host=app.config["REDIS_HOST"], port=app.config["REDIS_PORT"])
app.register_blueprint(basic, url_prefix="/api/v1")
api/resources/basic.py
from flask import current_app
from flask import Blueprint
from webargs import fields
from webargs.flaskparser import use_args
mod = Blueprint('basic', __name__)
write_args = {"value": fields.Str(required=True)}
@mod.route('/<str:key>', methods=['POST'])
@use_args(write_args, key)
def create_resource(args, key):
"""POST resource to redis."""
current_app.redis.set(key, args["value"])
current_app.logger.info("inserted value into redis")
return {key: args["value"]}, 201
@mod.route('/<str:key>', methods=['GET'])
def retrieve_resource(key):
"""GET value from redis."""
return {key: current_app.redis.get(key)}, 200
Is it possible to have a 'global' app context where you can put objects shared across request contexts, where you would access objects that you don't want to keep reinstantiating because it might be expensive and because of the convenience and how it makes it easier to reason about where 'objects' live. Like current_app.redis
, or current_app.logger
, or current_app.kafka_producer
. I read about Depends, and saw the examples provided for how to deal with dependencies / resources but I didn't see something like the above.
Might be a bad practice, but it's worked well for me so far.
How can I make use of starlette background feature inside FastApi?
Is your feature request related to a problem? Please describe.
I have a certain number of APIRouter, with for each of those a certain number of routes.
I want all routes that belong to a given APIRouter to have the same tag, and currently I'm achieving this by adding tags=['Tag1']
to each and every route.
Describe the solution you'd like
I got the feeling that I should be able to add the tags keyword directly to APIRouter and that all routes belonging to it inherit the tag.
Not sure it makes sense though but I feel it would avoid some useless repetition
This is a splinter conversation from #16
The docs for FastAPI say that you should raise an exception when an error occurs in your route logic, not return an object. Per #39, it seems like an elegant way to handle errors and I like it a lot.
In following with that pattern, I wonder if it is possible to extend the @app.exception_handler
decorator to specify a Pydantic object that will be returned, the same way a standard @app.get
decorator would? This might make the feature requested in #16 a little cleaner -- you could specify a list of codes that a route might throw, and the API documentation generator could figure it out from there.
Example code based on the suggestion:
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
class GenericHTTPError(BaseModel):
status_code: int
detail: str
items = [Item(name="foo"), Item(name='bar')]
app = FastAPI()
@app.get('/items/{item_id}', response_model=Item, errors=[404])
async def get_item(item_id: int):
if item_id not in items:
raise HTTPException(status_code=404, detail="Item not found")
return {"item": items[item_id]}
@app.exception_handler(HTTPException, response_model=GenericHTTPError)
async def generic_error(request, ex):
return GenericHTTPError(status_code=ex.status_code, detail=ex.detail)
I feel like I'm missing some details, but what do you think?
Awesome project you have going on! Keep up the good work! ๐
I was reading through the docs and in the Extra Models section, the About **user_dict
sub-section doesn't explain why there is a difference between using **user_dict
vs **user_in.dict()
.
Also I wasn't sure if you meant to specify user_dict
as a generic dictionary for the section as that object doesn't exist in the above code example, or did you mean to also continue to use user_in
?
I'm trying to follow the SQLAlchemy part of the tutorial but I'm having problems because after several requests I'm running out of sessions. Clearly I should be closing them at some point, but I don't quite know how or when. This is also my first time using SQLAlchemy, so that doesn't help. :)
Should I be using the Starlette database middleware instead? If so, can I still integrate it with the nice SQLAlchemy models?
Is your feature request related to a problem? Please describe.
I need the ability to use the Extra.forbid config option to indicate when I have extra values in my pydantic model. This feature landed in v0.19.0 and was fixed/enhanced in v0.20.0. There appears to be one breaking change in v0.20.0 since v0.18.2 (which is what is currently locked for fastapi)
Describe the solution you'd like
I'd like to update to pydantic v0.20.0. I can generate a PR for this, but I'm not sure why you locked it at v0.18.2
Describe the bug
if you run isort locally, it sorts the fastapi package as a 3rd party package, so once you push a branch on travis, isort there will fail
I think PyCQA/isort#541 (comment) describes it well
To Reproduce
Expected behavior
to run isort locally and have travis succeed without having to change fastapi import orders
Environment:
import fastapi
print(fastapi.__version__)
python --version
Additional context
Add any other context about the problem here.
Do this:
main_app = FastAPI()
sub_api = FastAPI()
...
main_app.router.routes.append(Mount('/subapi', app=sub_api))
sub_api
will correctly serve ever /subapi
-- docs, methods, all that. However, the docs will still look for /openapi.json
(absolute link) when trying to load the openapi spec. Additionally, the spec will not be adjusted to have the correct links, relative to where the module is mounted.
Perhaps this is a corner use case, but a lot of apps might have different collections of routes mounted in different subpaths.
The use case:
I'm running FastAPI behind a nginx reverse proxy, at the path http://localhost/api/
. The documentation front ends (swagger and redoc) are expecting openapi.json
at http://localhost/openapi.json
but it's actually routed at http://localhost/api/openapi.json
.
Setting openapi_url
to /api/openapi.json
also changes the openapi.json
path, so now it's looking for (through the proxy) http://localhost/api/api/openapi.json
.
Ideally, it'd be great if we could specify the "public path" for the api. That's how e.g. vue does it
Thanks for your awesome project. It's really great!
I have a model with a datetime field that needs to be in ISO 8601 format in the response. And when I call json method from the model instance I get the right string, but the response from fastapi returns standart output:
from datetime import datetime, timezone
from fastapi import FastAPI
from pydantic import BaseModel
class ModelWithDatetimeField(BaseModel):
dt_field: datetime
class Config:
json_encoders = {
datetime: lambda dt: dt.replace(
microsecond=0, tzinfo=timezone.utc
).isoformat()
}
app = FastAPI()
model = ModelWithDatetimeField(dt_field=datetime.utcnow())
@app.get("/model")
def get_model():
print(model.json())
return model
So, in console I'll get right string representation:
{"dt_field": "2019-01-31T22:00:12+00:00"}
But in the response from server I'll get this:
{"dt_field": "2019-01-31T22:00:12.810220"}
When switching from Flask / Flask_Restplus to FastAPI, tests fail
A basic test for a Flask RestPlus API will be like
class IntegrationTests(unittest.TestCase):
def setUp(self):
self.app = app.test_client()
def test_base(self):
response = self.app.get('/')
self.assertEqual(response.status_code, 200)
but FastAPI don't have a test_client()
.
Solution
To have the tests pass, it would be nice, if FastAPI could provide a similar interface for Unittests (e.g. with Nose).
Greetings and congrats again for this amazingly well documented library, I'm happy Twitter made me discover this !
So I decided to dive a little bit into it, and I was in particular interested in the Starlette DatabaseMiddleware.
I then cloned the related test in Starlette and reworked it using FastAPI here: https://github.com/euri10/fastapi/blob/dbmiddleware/tests/test_dbmiddleware.py
so in this test we got:
one starlette instance of Starlette starlette=Starlette()
that makes the very same tests as in the test_database mentionned aboveand
one fastapi instance of FastAPI fastapi=FastAPI()
, whose routes have been adapted by me to take the new "framework" into account (mainly switching to app.get and app.post instead of app.route, making use of pydantic models etc,....)
Each instance is tested separately in a class, namely class TestStarletteStyle(): and class TestFastAPIStyle():
Obviously TestStarletteStyle passes like in the original file.
Interestingly if you change starlette=Starlette()
to starlette=FastAPI()
TestStarletteStyle passes also, which makes sense since if I got it correctly a fastapi.post
is the same as a fastapi.route, methods=["POST"]
However TestFastAPIStyle
fails at various points, all tests fails but not all asserts:
So there's seem to be something incorrect with the rollback setting, happy to dig further but you surely have ideas, if making a PR with my failing branch is ok let me know
Good day,
First of all - many thanks for creating this project. Such a relief - you really nailed the proper amount of "batteries included". And docs are great - not a given thing for such a young project.
I'm studying SQL Database example where you note that SQLAlchemy is not compatible with async hence you configure path using def
instead of async def
. However this example raises and eyebrow because it should block the whole server while database is executing - only that it does not because the magic you do by running request handlers through threadpool unless they are co-routines.
While this magic is nice convenience, don't you think I can confuse users, particularly those who are less experienced with the whole sync/async co-existence semantics in Python world?
My bottom line is that IMHO it worth adding a clear "Unless you define your request handlers as coroutines FastAPI will run them them in separate thread" note in the "SQL Databases" and "Concurrency and async / await" chapters. What do you think?
Me coming from aiohttp is used to have non-async request handlers for simple methods that don't involve any IO and this magical FastAPI behavior, while useful, would've caused a performance penalty on those methods.
Description
I have a pydantic model with Enum and Union parameters, and while they both appear in Schema, in a post route they are not displayed in the Example edit section.
I hesitated to file a bug but I;d prefer to ask if that's something that's feasible first.
I was surprised and made a small exercice, take this model:
class DisplayMe(BaseModel):
my_bool: bool
my_float: float
my_str: str
my_int: int
my_dict: dict
# my_list: list
# my_tuple: tuple
# my_set: set
# my_List_str: List[str]
# my_tuple_str_int: Tuple[str, int]
# my_dict_str_int: Dict[str, int]
# my_union_str_int: Union[str, int]
# my_enum: Enum
my_emailstr: EmailStr
my_name_email: NameEmail
my_urlstr: UrlStr
my_dsn: DSN
my_bytes: bytes
my_decimal: Decimal
my_uuid1: UUID1
my_uuid3: UUID3
my_uuid4: UUID4
my_uuid5: UUID5
my_uuid: UUID
my_filepath: FilePath
my_directorypath: DirectoryPath
my_path: Path
my_datetime: datetime
my_date: date
add this route:
@router.post("/testypes")
async def types(tt: DisplayMe):
return tt
should you uncomment any of the pydantic types commented in the DisplayMe
model above, then the Edit section is empty, there's nothing to edit.
But I can see them in schema, for instance on the below screen my_tuple
is visible in the Schema:
Now if I put them commented they are in the Edit section:
question is : is it possible to have the commented pydantic types in the swagger edit section, I'm mostyl interested in Union and Enum in fact :)
Is your feature request related to a problem? Please describe.
Would like favicon for Swagger/ReDoc. I generally have a ton of tabs open in my browser and it helps me figure out which one to open.
Describe the solution you'd like
I can enter a PR to add the favicon from a CDN service (https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/favicon-32x32.png) to the html file you generate for swaggerui and redoc.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.