Closed sylvoslee closed 4 years ago
As I see it FastAPI is basically starlette with Pydantic for serialisation, and then some extra spice. So a prerequisite to make the integration seamless, we need Pydantic serialisation support.
Wow, this can get quite big, it would end up to be a DRF-like framework when all is done, which would be awesome.
If we're going to have big plans in mind, might as well consider graphql support.
FastAPI already has integrations with Graphene, so it's only natural!
Since neither Graphene or FastAPI have any database dependency, shouldn't be too hard to get them working
Isn't the whole point of GraphQL so that one can request a compound object, or a partial one? How does Graphene ensure that performs well? Surely it would need to know about relationships etc, and the DB layer needs to be able to use the hints for performance optimization (e.g. prefetch/select related?)
Sounds like a naïve implementation would leave a LOT of room for optimization to me?
But still, baby steps. I still have to actually use Pydantic to see how it works... Or you can help us get there faster :grin:
@grigi Graphene is merely an interface, you implement all the object-gathering methods, the example in their website make it quite clear.
As for relationship performance, there are some clever things you can do by making use of how tortoise-orm defers QuerySet execution through await
Basically, you build your coroutines without awaiting them, and keep adding to them, and then you await at the end. I'm working on a big product that is using tortoise-orm but we're still at early stages, when we get to heavy production we plan to try to implement this sharded concept.
But you'd definitely need to extend Graphene base classes to accomodate await/async.
And you can also use transactions
Here's a simple pseudocode-ish concept:
class Query(TortoiseGraphQL):
queryset = None
def resolve_book(self, filter):
self.queryset = Book.filter(filter)
def resolve_author(self, filter):
self.queryset.prefetch_related('author')
async def resolve_all(self):
results = await self.queryset
return results.to_json()
schema = graphene.Schema(query=Query)
schema.execute('''
query {
Book {
Author
}
}
''')
Disclaimer : never actually used Graphene or GraphQL 😄
I used GraphQL from an consumer POV, and the thing that got me was how to make partial matches performant? Because the API I used didn't speed up if I requested a small portion. So obviously it was not very "smart" about it.
I have never used Graphene either. Still I'm more interested in Pydantic at this stage. I wonder if one could map Graphene over Pydantic? (for an initial naïve implementation) It's always easier to work on optimizations after you have working repeatable benchmarks. And since the GraphQL interface is well defined, we can do anything we want as long as the tests pass.
I did a talk about my experiences in optimization once. Where the first step after setting up a a benchmark suite and profiling the data was to remove nearly all the "obvious optimizations" as they actually made it slower…
Please report back with your experiences re building a GraphQL interface using this proposed stack?
I tested it in FastAPI and it was as straight forward as shown in the docs:
def create_app(r: APIRouter) -> FastAPI:
app = FastAPI()
app.include_router(r)
register_tortoise(
app, db_url=DATABASE_URL, modules={"models": ["app.db.postgres.models"]}, generate_schemas=True
)
return app
Probably what needs to be specified is that FastAPI is in fact a Starlette app and it can be initialized the same way.
Yes, we can do that. Also, we now have pydantic serialisation support, so we could also build an example that provides a more complete fastapi experience.
Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like A clear and concise description of what you want to happen.
Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.
Additional context Add any other context about the feature request here.