diff --git a/README.md b/README.md index e3ef4a2..49ccf5a 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ **Create APIs from CSV files within seconds, using fastapi.** -This is a Python package to create APIs from CSV files, using a lightweight & -fully customizable wrapper around [fastapi](https://fastapi.tiangolo.com/). Endpoints -and query parameters are auto-generated based on the column names and data types in the -CSV file. Its data is written to a (temporary) sqlite database, so the API is blazing +This is a Python package to create APIs from CSV files, using a lightweight & +fully customizable wrapper around [fastapi](https://fastapi.tiangolo.com/). Endpoints +and query parameters are auto-generated based on the column names and data types in the +CSV file. Its data is written to a (temporary) sqlite database, so the API is blazing fast even for huge files. ![](images/visual-demo.png) @@ -33,18 +33,22 @@ fastapi-csv people.csv # directly from URL fastapi-csv https://raw.githubusercontent.com/jrieke/fastapi-csv/main/people.csv + +# With options : specify the delimiter character in the CSV, the host and port for the server +fastapi-csv people.csv --delimiter "|" --host "127.0.0.1" --port 1234 + ``` -Either command should start a fastapi instance, which has auto-generated endpoints and -query parameters based on the CSV file. Here, the API has an endpoint `/people` -(same name as the file), which can be queried using the CSV's column names, e.g. you can +Either command should start a fastapi instance, which has auto-generated endpoints and +query parameters based on the CSV file. Here, the API has an endpoint `/people` +(same name as the file), which can be queried using the CSV's column names, e.g. you can do: - `/people?first_name=Rachel` - `/people?last_name=Johnson&age=48` - -Additionally, fastapi-csv creates some convenience query parameters for specific data -types, e.g. + +Additionally, fastapi-csv creates some convenience query parameters for specific data +types, e.g. - `/people&age_greaterThan=18` (for int/float) - `/people&age_lessThanEqual=18` (for int/float) @@ -72,7 +76,7 @@ uvicorn my_file:app **Extending the API** -The cool thing: `FastAPI_CSV` is just a wrapper around `FastAPI`. Therefore, you can do +The cool thing: `FastAPI_CSV` is just a wrapper around `FastAPI`. Therefore, you can do all the stuff you can do with a normal fastapi instance, e.g. add a new endpoint: ```python @@ -82,7 +86,7 @@ def hello(self): return {"Hello:", "World"} ``` -In the future, you will also be able to easily modify existing endpoints that were +In the future, you will also be able to easily modify existing endpoints that were generated from the CSV file. @@ -94,5 +98,5 @@ If your CSV file changes, you can update the API data with: app.update_database() ``` -Note that this will only update the data, not the API endpoints or query parameters. +Note that this will only update the data, not the API endpoints or query parameters. To do that, you need to create a new `FastAPI_CSV` instance or re-start uvicorn. diff --git a/fastapi_csv/applications.py b/fastapi_csv/applications.py index aa61de6..8cdac65 100644 --- a/fastapi_csv/applications.py +++ b/fastapi_csv/applications.py @@ -59,7 +59,7 @@ class FastAPI_CSV(FastAPI): # # Return modified results so they get passed to the user. # return results - def __init__(self, csv_path: Union[str, Path]) -> None: + def __init__(self, csv_path: Union[str, Path], delimiter: Union[str, str]) -> None: """ Initializes a FastAPI instance that serves data from a CSV file. @@ -70,6 +70,7 @@ def __init__(self, csv_path: Union[str, Path]) -> None: # Read CSV file to pandas dataframe and create sqlite3 database from it. self.csv_path = csv_path + self.delimiter = delimiter self.table_name = Path(self.csv_path).stem self.con = None df = self.update_database() @@ -134,8 +135,8 @@ def query_database(self, sql_query): def delete_database(self): """ - Deletes the database with all data read from the CSV. - + Deletes the database with all data read from the CSV. + The CSV file is not deleted of course. The API endpoints are also not affected, so you can use `update_data` to read in new data. """ @@ -149,9 +150,9 @@ def delete_database(self): def update_database(self): """ Updates the database with the current data from the CSV file. - + Note that this only affects the database, not the endpoints. If the column names - and/or data types in the CSV change (and you want that to update in the + and/or data types in the CSV change (and you want that to update in the endpoints as well), you need to create a new FastAPI_CSV object. """ self.delete_database() @@ -164,7 +165,7 @@ def update_database(self): # Download excel file from Google Sheets, read it with pandas and write to # database. - df = pd.read_csv(self.csv_path) + df = pd.read_csv(self.csv_path, delimiter=self.delimiter) self.con = sqlite3.connect(":memory:", check_same_thread=False) df.to_sql(self.table_name, self.con) diff --git a/fastapi_csv/cli.py b/fastapi_csv/cli.py index 5647f2b..a5eca21 100644 --- a/fastapi_csv/cli.py +++ b/fastapi_csv/cli.py @@ -14,17 +14,18 @@ @typer_app.command() def main( csv_path: str = typer.Argument(..., help="Path to the CSV file"), + delimiter: str = typer.Option(",", help="Delimiter character in the CSV file"), host: str = typer.Option("127.0.0.1", help="IP to run the API on"), port: int = typer.Option(8000, help="Port to run the API on"), ): """ 🏗️ Create APIs from CSV files within seconds, using fastapi. - + Just pass along a CSV file and this command will start a fastapi instance with auto-generated endpoints & query parameters to access the data. """ typer.echo(f"🏗️ Creating API from CSV file: {csv_path}") - app = FastAPI_CSV(csv_path) + app = FastAPI_CSV(csv_path, delimiter) typer.echo("🦄 Starting with uvicorn...") typer.echo( "💡 Check out the API docs at "