Skip to content
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

Support for FastAPI pydantic response models #46

Open
garry-jeromson opened this issue Dec 12, 2020 · 5 comments
Open

Support for FastAPI pydantic response models #46

garry-jeromson opened this issue Dec 12, 2020 · 5 comments
Labels
enhancement New feature or request question Further information is requested

Comments

@garry-jeromson
Copy link

garry-jeromson commented Dec 12, 2020

FastAPI supports using pydantic models to define JSON response bodies for REST API endpoints; making FHIR resources compatible with this support would take the usability of the library to a higher level.

I'm new to the library so I don't know more about how it uses pydantic other than what is stated in the README; in any case, however pydantic is currently used, it doesn't seem to be compatible on first look. The only requirement for compatibility with FastAPI is that the response model class is derived from pydantic's BaseModel.

A super basic example using the Practitioner resource from release 5.1.1, with FastAPI 0.62.0 and pydantic 1.7.3, is as follows:

from fastapi import APIRouter
from fhir.resources.practitioner import Practitioner

router = APIRouter()

@router.get(
    "/practitioner",
    response_model=Practitioner,
)
def get_practitioner(
) -> Any:
    return Practitioner()

This gives a couple of runtime errors on endpoint setup:

RuntimeError: no validator found for <class 'fhir.resources.practitioner.Practitioner'>, see `arbitrary_types_allowed` in Config
Invalid args for response field! Hint: check that <class 'fhir.resources.practitioner.Practitioner'> is a valid pydantic field type

This makes some sense, as the Practitioner resource (and most other resources, it would seem) derive from FHIRAbstractBase, and not pydantic's BaseModel.

Is FastAPI support something that's been considered already? Am I missing anything obvious regarding the use of pydantic?

@nazrulworld
Copy link
Owner

nazrulworld commented Dec 12, 2020

I think we have support the FastAPI typing methodology.
try

from fastapi import APIRouter
from fhir.resources.practitioner import Practitioner
from fhir.resources.fhirtypes import PractitionerType

router = APIRouter()

@router.get(
    "/practitioner",
    response_model=PractitionerType,
)
def get_practitioner(
) -> Any:
    return Practitioner()

Let us know if you face any problem.

@nazrulworld nazrulworld added the question Further information is requested label Dec 12, 2020
@garry-jeromson
Copy link
Author

Thanks! This kind of works, in that the code runs, but the response model is incorrect and it doesn't play nice with FastAPI's OpenAPI documentation generation:

  • The OpenAPI doc generators can't parse the response model, and gives the message "Unknown Type: Practitioner"
  • The response model contains a bunch of private fields:
{
  "fhir_comments": null,
  "id": null,
  "_id": null,
  "implicitRules": null,
  "_implicitRules": null,
  "language": null,
  "_language": null,
  "meta": null,
  "contained": null,
  "extension": null,
  "modifierExtension": null,
  "text": null,
  "active": null,
  "_active": null,
  "address": null,
  "birthDate": null,
  "_birthDate": null,
  "communication": null,
  "gender": null,
  "_gender": null,
  "identifier": null,
  "name": null,
  "photo": null,
  "qualification": null,
  "telecom": null,
  "resourceType": "Practitioner"
}

If improved FastAPI support is something you'd be open to adding to the library, I'm happy to work on a pull request to see if we can fix these issues.

@nazrulworld nazrulworld reopened this Jan 6, 2021
@nazrulworld
Copy link
Owner

@garry-jeromson you are welcome to make your pull requests. we are fully open to add any new feature.
Just keep in mind that the new feature should not make any new mandatory package dependency as well as not violating FHIR Resource specification.

@nazrulworld nazrulworld added the enhancement New feature or request label Jan 6, 2021
@pcorazao
Copy link

if we add this to here: https://github.com/nazrulworld/fhir.resources/blob/main/fhir/resources/fhirabstractmodel.py#L516
We can remove all the _ properties from showing up on the Schema for FastAPI Swagger.

@staticmethod
        def schema_extra(schema: Dict[str, Any], model: Type['FHIRAbstractModel']) -> None:
            current_schema = schema.get('properties', {})

            for key in list(current_schema.keys()):
                if "_" in key:
                    current_schema.pop(key)

My next question is.. how do we get the sub models to render in FastAPI? if we do something like this:
name: HumanName = Field( None, alias="name", title="A name associated with the patient", description="A name associated with the individual.", # if property is element of this resource. element_property=True, ) i.e. removing the typing.List[fhirtypes.HumanNameType] we are nearly there, you get both the HumanName added to the Schema, but it also plugs in the full contract into the name field as well. Which might be problematic for some of the larger resources.

I don't know if there is a way to keep HumanNameType and then like.. simply add the HumanName to the Schema somehow?

@gilmorera
Copy link

What's the status on FastAPI? Is there any inherit functionality for fastAPI in this repository or is there a 3rd party tool now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants