This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why not use the return type annotation for the response_model? #101
Comments
That was the original idea, but then there was no way to put the status code in the same annotation. Or if the status code was there then the response model would have to be the parameter. And the same with the response description. Also, because in many cases the function doesn't really return an |
thanks for the explanation. Maybe add some of that to the docs ? To be honest - I had the same reaction. Working thru the tutorial - you first see query params and body as type inferred from the hints. So it's a little surprising to see response needing to be marked explicitly. The reasons make sense - so a quick note would help clear things up for new users. |
Created a pull request at: |
) * Update response model documentation to explain design choice Closes #101 * 📝 Update note about return function type annotation
Thanks for the idea @Imaclean74 Thanks for the PR @JHSaunders 🎉 🌮 |
Huh, I'm trying to evaluate/learn in FastAPI, and I have searched like mad for an explanation on this. :) But I don't quite get this statement, @tiangolo:
When/where would users see type errors? How is that different from function parameters that initialize an Also, perhaps one should not dismiss the use of function return types for response schema deduction. Return types are the most natural way to describe a response. An idea for a (backward-compatible) approach: @app.get('/hello')
def hello() -> Greeting: # ... would behave as if it was written as: @app.get('/hello', response_model=Greeting)
def hello() -> Greeting: # ... but @app.get('/hello', response_model=Greeting)
def hello() -> dict: # ... would ignore the function's return type (at least for the API documentation). Any thoughts? |
@zor-el this breaks from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
title: str
description: str = None
fake_db = {
"foo": {
"title": "Fighters",
"description": "There goes someone's hero"
}
}
app = FastAPI()
@app.get("/item/{item_id}")
def read_item(item_id: str) -> Item:
return fake_db.get(item_id) The Also, the idea/benefit of type annotations is to help you use them in the rest of your code. To detect errors, have completion, etc. But a path operation function is never called by yourself. It's called by FastAPI. So, there's no real benefit in adding a return annotation to the functions. Even though at first it seems the more intuitive place to declare that. About this:
In the latest version, when you import and use That involved quite some work just to make Adding return annotations would bring the same kind of problem. |
Even if the function is only called by framework code, I still find specifying a return type useful to statically ensure that I return the correct value from my request handler. Specifying that in the Another reason for adding an explicit return value for my request handlers is that my mypy settings simply force me to annotate every function. I find that useful to ensure I don't forget it sometimes. But with the current FastAPI behavior, this forces me to repeat myself, e.g.: @app.get("/", response_model=Result)
def handle() -> Result:
... So in my mind it would be valuable (and, as you mention, more intuitive) if FastAPI would pick up the return type as a default Just my two cents. Btw, thanks for your great work on this project! |
If this snippet (from @tiangolo example above): @app.get("/item/{item_id}")
def read_item(item_id: str) -> Item:
return fake_db.get(item_id) raises @app.get("/item/{item_id}")
def read_item(item_id: str) -> Item:
return Item(**fake_db.get(item_id)) and catch @app.get("/item/{item_id}", response_model=Item)
def read_item(item_id: str):
return fake_db.get(item_id) |
For completeness, if @app.get("/item/{item_id}", response_model=Item)
def read_item(item_id: str) -> Any:
return fake_db.get(item_id) |
I think having the response_model automatically inferred from the annotation as an alternative to explicitly passing it would be beneficial. In the case where response_model is not set fastapi would simply use This allows people who prefer explicitly converting the types themselves to use mypy and benefit from static analysis. Everybody else could still use the argument to the decorator. Furthermore this would allow for checks like the following: from myapp.models import UserModel
from myapp.db import fake_db, Manager, Employee
@app.get("/managers/{manager_id}", response_model=UserModel)
def get_manager(manager_id: str) -> Manager:
return fake_db.Managers.get(manager_id)
@app.get("/employees/{employee_id}", response_model=UserModel)
def get_user(employee_id: str) -> Employee:
return fake_db.Employees.get(employee_id) This way they get the checks from mypy which ensure the are returning the correct thing while simultaneously benefiting from pydantic reducing them to a common user model. |
I also think it would be more consistent with the rest of the framework. The |
This was added in #1436 🚀 It's available in FastAPI You can read the new docs here: https://fastapi.tiangolo.com/tutorial/response-model/ 🤓 |
given that FastAPI `response_model` now support return type annotation see more details at: 1. tiangolo/fastapi#101 2. tiangolo/fastapi#1436
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Description
This is a very minor question on chosen syntax. Why not use the return type annotation for the response_model? For example rather than:
You could concievably go:
which just seems like it uses the language facilities better and is a bit more pythonic. There is no real change in feature set, and I am sure i was thought of, but what was the reasoning behind not doing it?
The text was updated successfully, but these errors were encountered: