Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 14:09
    hesummerzh commented #2907
  • 13:51
    snow6oy commented #911
  • 13:10
    Suyoung789 edited #2908
  • 13:09
    github-actions[bot] commented #2908
  • 13:08
    codecov[bot] commented #2908
  • 13:08
    codecov[bot] commented #2908
  • 13:06
    codecov[bot] commented #2908
  • 13:06
    codecov[bot] commented #2908
  • 13:06
    Suyoung789 synchronize #2908
  • 10:03
    github-actions[bot] commented #2908
  • 10:01
    codecov[bot] commented #2908
  • 10:01
    codecov[bot] commented #2908
  • 10:00
    codecov[bot] commented #2908
  • 10:00
    codecov[bot] commented #2908
  • 10:00
    codecov[bot] commented #2908
  • 10:00
    codecov[bot] commented #2908
  • 10:00
    Suyoung789 synchronize #2908
  • 09:58
    codecov[bot] commented #2908
  • 09:58
    codecov[bot] commented #2908
  • 09:58
    Suyoung789 synchronize #2908
Manu
@ebreton

yeah, I think Tom Christie's https://github.com/encode/orm is on the right track, I just wish it had pydantic integration

agreed. thanks for the link

euri10
@euri10
I only uses encode/databases
Sebastián Ramírez
@tiangolo

@tiangolo does FastAPI support serialization / parsing of pydantic models with custom root types? If not, would you be interested in supporting it? It seems like serialization could be accomplished with a minimal change to jsonable_encoder to look for __root__, and parsing through the use of parse_obj (not sure if that is used for parsing yet).

@dmontagu , @euri10 __root__ is useful for people using Pydantic alone, but as @euri10 says, in FastAPI it doesn't provide any advantage. response_model and any FastAPI path operation parameter are not interpreted as just Pydantic models, but Pydantic Fields. (Pydantic's Field class). So, they can take anything that a Pydantic model attribute can take, any Python type (including Pydantic models).

Manu
@ebreton

you can watch how I integrated alembic here @ebreton https://gitlab.com/euri10/euri10_fastapi_base/blob/master/backend/app/migrations/env.py#L31

that's nice :star2: thanks @euri10 ! With regards to nested objects and missing SQLalchemy ORM, how have you handled that ? I can see in your example that user_settings have a relationship to users, but it doesn't look like you are making use of it in the code

euri10
@euri10
Brand new table yes I haven't used it much indeed. In other projects I rarely have that deep relationships so really can't comment on whether or not sqlalchemy core would be a pain in the a**
On a particular project I'm making deep use of ordinality and unnest and managed a way to write the query in core,honestly I doubt it's feasible with orm, and the raw query is just more readable
gargleblaster
@gargleblaster

Hi, I'm very new to FastAPI. Thanks for your work! I am trying to handle a 302 to allow the user to complete an OAuth authorization. I have tried returning the response from the Python requests library, which is indeed a 302, directly to the browser, but I get an exception. It seems that FastAPI is trying to look inside of the response, rather than just passing it along. How can I resolve this?

DEBUG:main:login response: <Response [302]>
INFO:uvicorn:('67.191.210.63', 58131) - "GET /login HTTP/1.1" 500
ERROR:uvicorn:Exception in ASGI application
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 368, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/usr/local/lib/python3.7/site-packages/engineio/async_drivers/asgi.py", line 53, in call
await self.other_asgi_app(scope, receive, send)
File "/usr/local/lib/python3.7/site-packages/starlette/applications.py", line 133, in call
await self.error_middleware(scope, receive, send)
File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 122, in call
raise exc from None
File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 100, in call
await self.app(scope, receive, _send)
File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 73, in call
raise exc from None
File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 62, in call
await self.app(scope, receive, sender)
File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 585, in call
await route(scope, receive, send)
File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 207, in call
await self.app(scope, receive, send)
File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 40, in app
response = await func(request)
File "/usr/local/lib/python3.7/site-packages/fastapi/routing.py", line 122, in app
skip_defaults=response_model_skip_defaults,
File "/usr/local/lib/python3.7/site-packages/fastapi/routing.py", line 63, in serialize_response
return jsonable_encoder(response)
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 110, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 66, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 110, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 66, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 110, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 66, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 110, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 66, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 103, in jsonable_encoder
raise ValueError(errors)
ValueError: [KeyError(<class 'object'>), TypeError("'object' object is not iterable"), TypeError('vars() argument must have dict attribute')]

gargleblaster
@gargleblaster
Here is the working code:
def login(response: Response):
    resp = getAuthCode()
    response.status_code = 302
    response.headers['Location'] = resp.headers['Location']
    logger.debug(f'login response: {response}')
    return response
Sebastián Ramírez
@tiangolo
@gargleblaster I think you might nave an old version of FastAPI. It's better to create an issue in GitHub, that way I (or someone else) can check it.
gargleblaster
@gargleblaster
@tiangolo Thanks for your reply. I am running 0.31.0, which doesn't seem very old. Are you saying that my code above should have been unnecessary, and that the 302 response should have been passed through? (Understood about creating an issue in GitHub, but I assumed this was not a bug but operator error. :-)
gargleblaster
@gargleblaster
@tiangolo Sorry, I am actually using your docker image: tiangolo/uvicorn-gunicorn-fastapi:python3.7, so that turns out to be 0.30.1.
chbndrhnns
@chbndrhnns
Hey, I would like some inspiration on how I could implement role-based access with fastAPI. I know for Flask, there is flask-rbac, for example.
William Hayes
@wshayes
Are you getting your roles from the JWT token? a db user query? Did you want to do it as a decorator? You’ll need to add role access control logic to each endpoint you want to protect.
skaaptjop
@skaaptjop
auth-auth is always a fun topic.
I like the fact that certain frameworks remain lightweight. Allows us to choose the pattern that fits the use-case best. It is certainly quite straightforward to "port" any flask lib to a fastapi implementation because the basic principle of request/response/middleware/endpoint is the same foreverything
chbndrhnns
@chbndrhnns

Are you getting your roles from the JWT token? a db user query? Did you want to do it as a decorator? You’ll need to add role access control logic to each endpoint you want to protect.

A db query, probably. I was hoping for an existing solution in the starlette world, to be honest.

Francesco Bartoli
@francbartoli

Are you getting your roles from the JWT token? a db user query? Did you want to do it as a decorator? You’ll need to add role access control logic to each endpoint you want to protect.

Hi @wshayes getting roles/claims from a JWT token is a super interesting topic for me but I’m curious what is your suggestion

Neil Shapiro
@nrshapiro
So in my api I'm returning a pydantic model, and fastAPI is converting it to json. If I test or demonstrate a endpoint directly via the browser (rather than through docs), is there a way to get FastAPI to prettyprint (indent) the json?
Neil Shapiro
@nrshapiro
Also, and more importantly, how do I make the pydantic fields in a model return only what's not defaulted to "None" in the model? If I don't set a default to None, then the model produces an error because the field is "required". If I default them to None, they all show up in the response to the client--in the API I'm replacing, those fields should remain absent, reducing the data return and also showing up in the client as undefined (and the client actually tests for that).
James Vogel
@voglster
so i have me head wrapped around authentication and creating a jwt. I also added a graphql endpoint on my app to query some objects. What I would like to do is add authentication to the GraphQLApp. can you use the depends syntax current_user: User = Depends(get_current_active_user)) when using app.add_route for graphql?
James Vogel
@voglster
either that or how can i make the graphql endpoint require a jwt?
euri10
@euri10

So in my api I'm returning a pydantic model, and fastAPI is converting it to json. If I test or demonstrate a endpoint directly via the browser (rather than through docs), is there a way to get FastAPI to prettyprint (indent) the json?

it's already the case @nrshapiro the returned json is indented, see this screen for instance:

Imgur

as for the defaults you may try dict(skip_defaults=True)
William Hayes
@wshayes
@nrshapiro https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_skip_defaults-parameter may work - it works if you are creating the Pydantic model directly - if you are setting the defaults any way other than that (e.g. the defaults are set by code other than Pydantic model creation) it won’t clean them out. I have a recursive function that will clean out anything null’ish for responses.
@francbartoli It’s pretty straightforward to add claims/roles to JWT’s and then use them (after authentication) to determine what a user has access to - it cuts down on DB queries. The only problem with it is you cannot expire the token early (e.g. your user has a new role added to them and their token is still good for X minutes). Until their token expires or you have someway to force a token update - they won’t see the benefit of the new role. If you are using websockets, you could use that to trigger a token update.
William Hayes
@wshayes
You can add any fields you want to a JWT payload. I’ve seen tokens that have several dozen fields and are around 4kb in size - I think that’s a bit overdoing it :) It’s not a problem from the JWT spec/browsers/servers - just adds more IO to each request.
euri10
@euri10
my googling skills are failing short : is there a way on a running app, to get gunicorn config params ? I know I can run with gunicorn -c config but I've got a machine where I setup some params and I'm not positive they have been loaded
Omri Har-Shemesh
@omrihar
Hello everyone! We've been hit with a weird issue and I'm wondering if anyone has experienced this before: we deployed the fastapi fullstack app to AWS cloudfront using traefik and for some reason we don't manage to get query parameters to pass to our API endpoints. We get None instead if there is not default value set. What is weird is that the API docs work and also the api works when no query parameters are needed. Any suggestions as to where the culprit could lie?
William Hayes
@wshayes
You have your application assets on Cloudfront? but not Traefik or FastAPI right?
Omri Har-Shemesh
@omrihar
Just as I posted this we managed to solve it - we didn't define cloudfront to forward query parameters!
So once we did this and waited the long time it takes to update it works.
Thanks!
euri10
@euri10
:bug: :)
William Hayes
@wshayes
Cool - thanks for sharing!
Omri Har-Shemesh
@omrihar
It was a sneaky one thou because we mostly had defaults that work and we didn't notice that the parameters don't change - until there was a default that didn't work in a specific setting
Francesco Bartoli
@francbartoli

You can add any fields you want to a JWT payload. I’ve seen tokens that have several dozen fields and are around 4kb in size - I think that’s a bit overdoing it :) It’s not a problem from the JWT spec/browsers/servers - just adds more IO to each request.

Thanks @wshayes, my first thought is to find a viable solution to receive authorization claims/roles from an external authentication system and spend it over a microservices architecture based on FastAPI

William Hayes
@wshayes
AWS Cognito, Auth0 and others allow you to add roles/claims and other user metadata as user attributes to the token. Note that the new Auth0 javascript library makes it much more difficult to get a JWT (instead they share a simple access token unless you slap it hard upside the head). I’ve not used Cognito yet, but I’ve been eyeing it as Auth0 seems to make hard things harder rather than slightly easier.
Neil Shapiro
@nrshapiro

@euri10, that's only the case in Docs as I mentioned. But others may show it in Google Chrome or elsewhere, where it looks like this:

image.png

euri10
@euri10
skaaptjop
@skaaptjop
@francbartoli another lighter weight solution is Google's firebase. Extremely straightforward to handle auth.
Francesco Bartoli
@francbartoli
Yep @skaaptjop, I played a bit with Firebase Auth but did not manag claims/roles at that time
skaaptjop
@skaaptjop
claims in FB are very lightweight (max 1000b I believe) so they do kinda expect any role based or other scheme to be implemented around it (with firestore for example)
David Montague
@dmontagu
@nrshapiro You can modify how the serialization happens by changing the response_class argument on your endpoint
the default response class (starlette.responses.JSONResponse) looks like this:
class JSONResponse(Response):
    media_type = "application/json"

    def render(self, content: typing.Any) -> bytes:
        return json.dumps(
            content,
            ensure_ascii=False,
            allow_nan=False,
            indent=None,
            separators=(",", ":"),
        ).encode("utf-8")
if you subclass and modify the render method to set indent=4 and separators=(", ", ": ") in json.dumps I think it will render closer to the "pretty" way
something like this:
import json
import typing

from starlette.responses import Response

class PrettyJSONResponse(Response):
    media_type = "application/json"

    def render(self, content: typing.Any) -> bytes:
        return json.dumps(
            content,
            ensure_ascii=False,
            allow_nan=False,
            indent=4,
            separators=(", ", ": "),
        ).encode("utf-8")