You would want to call the API as few times as possible. FastAPI has built in streaming support.
https://fastapi.tiangolo.com/advanced/custom-response/?h=stream#streamingresponse
​
It really should be as simple as using the streaming response. The hard part is making the API/UI robust to network dropouts, missing packets, and anything else that could happen during a 1+ hour video stream. Breaking the video into chunks, using a python lib that can seek in the video, using compression, keeping play state of a video for the user in a DB so you can resume at any point.
All of that makes video streaming hard.
def create_student(student: schemas.StudentCreate
The typehint here controls the validation. Assuming StudentCreate is a Pydantic model with a `gpa` field defined, then any requests missing that field will return an appropriate error auto-magically.
It's not uncommon to have a lot of text and documentation in your code. In fact, it's considered good practice, as that's where it belongs - next to your code.
Personally, I try to keep text in the Field.description
short with longer, more descriptive text in docstrings.
Forget that comment, you still want to have local env to test things out, you can think about dockerizing the app later. There is a great section about that in the docs.
I’m in the very slow process of migrating a giant Flask app to FastAPI. I want to make breaking changes as part of the change anyway, so I have the new API at a new URL. Instead of moving paths, I’m adding features to the new API one by one and cutting over consumers (e.g. UI components) as they’re ready.
If you want to take a more unified approach, rather than having a completely new API, perhaps this (https://fastapi.tiangolo.com/advanced/wsgi/) will help?
I think Dependency injection is more relevant than middleware in your case.
I have a project where a few systems endpoints can only be accessed by staff users on our Django site. So the endpoint looks like this. The celery_router
will use admin_auth_router
authentication.
app.include_router( celery_router.router , prefix = '/celery' , tags = ['Celery'] , dependencies = [ fastapi.Depends(admin_auth_router.require_user_login) ] )
But users do have access to reports & we use Google SSO. So any user would be able to access the endpoint. The reports_router
will use google_router
authentication.
app.include_router( reports_router.router , prefix = '/reports' , tags = ['Reports'] , dependencies = [ fastapi.Depends(google_router.require_user_login) ] )
I know that the use-case is not exactly the same, but it does seem pretty close.
I'm with you on the Depends injections. And implementing them as default values for function parameters is odd, to say the least.
But overall, it's a great piece of software so....
Also if you don't like having to repeat deps in function sigs, you can add deps to path decorators and/or router instance.
https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/
Start with the docs. It's a great place to not only learn FastAPI -- but design patterns, async/await, and software architecture in general as well!
Check out https://testdriven.io/blog/topics/fastapi/ for a few additional tutorials on-
Seems fine from what I see!
For project template structure you can this page: https://fastapi.tiangolo.com/project-generation/
GitHub link:
https://github.com/tiangolo/full-stack-fastapi-postgresql
But you can adapt as per the scale of your application
You can use any database with FastAPI. It's just a web framework. You don't have to use the same ORMs shown in the tutorials.
> FastAPI works with any database and any style of library to talk to the database.
> A common pattern is to use an "ORM": an "object-relational mapping" library.
Direct quote from the docs here: https://fastapi.tiangolo.com/tutorial/sql-databases/
FastAPI's documentation has a [section](https://fastapi.tiangolo.com/tutorial/security/) about setting up authentication for the API. I'd like to say though that authentication is no joke, it's the most difficult part of the system and from experience I can say most people get it wrong. If this is for internal use, you can consider putting the website in a private network only accessible through a VPN, and then maybe you don't need login at all?
Do you use Active Directory or something similar for internal logins in your company? If you do, you can build an integration with that to handle the logins. In that case, you'd only need to worry about validating JWT tokens. Again, not something necessarily easy to do (and AD in particular has significant gotchas). For token validation I've done a tutorial myself.
The final question is do you really need FastAPI for this? For an internal admin site, like u/Cognizantauto95 says you'd be very well served with Django and its built-in admin site, with login included, database integration, and much more. You can also deploy the Django admin to a private network for security.
Looking at the documentation https://fastapi.tiangolo.com/tutorial/request-files/, the UploadFile object is already open, so you should be able to use it directly: object_id = calculate_md5(file)
, modifying the calculate_md5
function to
def calculate_md5(filename): file_hash = hashlib.md5() while chunk := f.read(8192): file_hash.update(chunk) return file_hash.hexdigest()
You might also try installing and using PyCharm Community Edition. It's free and tends to be one of the best IDEs for Python and virtual environment setup. It works very well with FastAPI, Uvicorn, etc.
Map each one(Auth etc) to the corresponding http status code in the response
kwarg here: https://fastapi.tiangolo.com/advanced/additional-responses/#additional-response-with-model
Also make sure to type hint all your models extending BaseModel so that the documentation can be generated and everything serialized properly at runtime.
I haven't tried it yet, but this use case is described succintly in the FastAPI docs
FastAPI supports async out of the box, and encode/databases provides async support for querying the database.
If you set up the connection to the database as a dependency, then you can override that dependency in the tests to return whatever you want.
https://fastapi.tiangolo.com/advanced/testing-database/
In this example, he sets the override to use a testing database, but if you can set it to just return a class or a mock object.
def get_conn(): return MongoUser
async def find_user(email: str = Query(None), mu=Depends(get_conn)) check_user_exists = mu.objects(email=email) . . .
In your testing file
class MockedClass(): def objects(email: str =None): return "" //Or whatever it should return
def override_get_user(): return MockedUserClass()
app.app.dependency_overrides[get_conn] = override_get_user
You're running into exactly what I said you would run into with a recursive function. Don't do this. Also, there is zero need to make app
a protected variable.
I think you should revisit some tutorials on fastapi.
Don't return a python data structure in a web call. Return a standardized data structure, json
in this case, and remove the response_model
parameter from your decorator. You don't need it unless you're actually going to use a model in your response, which you are not.
The problem is that while you might make the function Depend
on the get_db
you don't actually ever do anything with the database.
Look at your code and take out a rubber ducky if you need to. Your function is named new_internship
and it takes two parameters, internship
and db
. In your try
block you just call yourself with the same parameters, but nothing is ever done with the database other than getting a connection. This is equivalent to putting a car on a round racetrack and watching it go round and round and accomplish nothing because you've created a recursive operation.
@internships_router.post("/new-internship", response_model=dict) async def new_internship( internship: InternshipSchema, db: Session = Depends(get_db), ): try: # Internships_schema.validate(internship) await new_internship(internship=internship, db=db) return { "message": "created-internship", "internship": internship, "status_code": 200, } except Exception as err: return { "message": "Bad Data", "internship": f"Bad data. The Error is: {err} and the data you sent is {internship}", "status_code": 400, }
https://fastapi.tiangolo.com/advanced/wsgi/?h=wsgi#using-wsgimiddleware
Yea python web frameworks all share wsgi and/or asgi as common interfaces for running a server. Django can use either wsgi/asgi and fastapi can mount either asgi/wsgi.
Yes although I'm unsure how worthwhile it is(speaking strictly from a performance perspective) to even create routes specifically to isolate synchronous-only def
code.
https://fastapi.tiangolo.com/async/#path-operation-functions > If you are used to defining trivial compute-only path operation functions with plain def for a tiny performance gain (about 100 nanoseconds), please note that in FastAPI the effect would be quite opposite. In these cases, it's better to use async def unless your path operation functions use code that performs blocking I/O.
Which I'm interpreting as: "There's ~15ms overhead for running synchronous code in a thread/process pool executor. If your code block/function/etc runs faster than ~15ms a def
path(or manually using loop.run_in_executor) and is cpu-bound, you shouldn't use a def
path since it will just add overhead.". ORM calls figure to be blocking I/O so this doesn't necessarily apply, but you get the idea.
I wouldn't worry about trying to optimize all this though until you really have to.
I ended up using sqlacodegen to generate the models code to reflect and used it like the tutorial
Thanks for showing me that tool!
request: Request is supposed to reference a model, typically using Pydantic. Then the all lowercase request is what you'd use in your function.
https://fastapi.tiangolo.com/tutorial/response-model/
Here is a good introductory video that will walk you through it. https://www.youtube.com/watch?v=kCggyi_7pHg
Are you following the instructions from the documentation page? https://fastapi.tiangolo.com/tutorial/
To run the API you should use an ASGI server like uvicorn such as the documentation says
The OAUTH2 Scopes example in the docs uses username/password to generate a JWT, then uses the JWT to auth with scopes. The only part of the example that really uses "OAUTH" is
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends())
You should be able to replace the form_data...
with some other form of auth that works better for you. If the user already has a JWT (not sure how...) they can just use all the other routes in the OAUTH with Scopes example.
https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/
you don't NEED to use a different front end, if you just need a simple web page FastAPI can present static HTML pages and handle form data fine. I don't think this is the common use case though. as others have indicated using a JS based front end and interfacing with FastAPI via API's is the more common approach.
​
Information on processing form data can be found here: Form Data - FastAPI (tiangolo.com)
​
Presenting webpages w/ Jinja2 templates: Templates - FastAPI (tiangolo.com)
Sorry you got downvoted and no answers. This community wasn't very friendly to me either when I asked the same question last week. The only answer I got was one I left myself after I solved my own problem haha.
Basically you can't import from main.py in your routers because that would cause a circular dependency. There's already an import chain from your routers to main.py thanks to
app.include_router(<blah>)
The solution in the official docs is here: https://fastapi.tiangolo.com/tutorial/sql-databases/#create-a-dependency You'll have to tweak it a bit because the official docs seem to encourage giant monolithic files, rather than your simple project structure.
First, you have to move your common dependencies like db sessions to another file. I simply called mine database.py. Then you need to use FastAPI's Depends module to pass the shared resource to your routes. Looks something like this:
from database import get_db from sqlalchemy.orm import Session from fastapi import Depends .... @router.get("/items", response_model=List[schemas.items]) async def get_items(offset: int = 0, limit: int = 100, db: Session = Depends(get_db)): items = itemsDAO.get_items(db, offset=offset, limit=limit) return items
Your code to create the session goes straight in database.py. Then create a get_db function that returns the session. The source code from the docs worked perfectly for my get_db.
It’s been a minute since I’ve used flask (I can’t remember flash off the top of my head) but hopefully this helps cover what you’re looking for:
https://fastapi.tiangolo.com/tutorial/request-files/
Essentially you just need to create a POST endpoint for multipart form data.
Then wire that up in your front-end framework of choice or use a curl POST.