Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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.


Expand All @@ -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.
13 changes: 7 additions & 6 deletions fastapi_csv/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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()
Expand Down Expand Up @@ -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.
"""
Expand All @@ -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()
Expand All @@ -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)

Expand Down
5 changes: 3 additions & 2 deletions fastapi_csv/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down