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

Refactor and add database support. #2

Merged
merged 3 commits into from Dec 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .dockerignore
@@ -0,0 +1,3 @@
.git/
.venv/
__pycache__/
4 changes: 4 additions & 0 deletions .env.example
@@ -0,0 +1,4 @@
DB_NAME=
DB_USERNAME=
DB_PASSWORD=

1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -138,3 +138,4 @@ dmypy.json
# Cython debug symbols
cython_debug/
.vscode/

16 changes: 16 additions & 0 deletions Dockerfile
@@ -0,0 +1,16 @@
FROM python:3.9-slim-buster

ARG POETRY_VERSION=1.1.12

ENV PYTHONUNBUFFERED=1
ENV PYTHONPATH "${PYTHONPATH}:/app"

RUN pip install "poetry==$POETRY_VERSION" && poetry config virtualenvs.create false

WORKDIR /app

COPY poetry.lock pyproject.toml /app/

RUN poetry install --no-interaction --no-ansi

CMD ["poetry", "run", "uvicorn", "--host", "0.0.0.0", "nepali_dictionary.main:app", "--reload"]
8 changes: 8 additions & 0 deletions Makefile
@@ -0,0 +1,8 @@
dev:
docker-compose up

migrate:
docker-compose exec app poetry run python migrations/

seed-db:
docker-compose exec app poetry run python seed/
39 changes: 36 additions & 3 deletions README.md
Expand Up @@ -8,10 +8,43 @@ You can say this is just the API version of that project.

## Documentation

Visit https://nepalidict.herokuapp.com/docs
### Setting up the project locally.

There is only one endpoint for now, which seems to be sufficient.

#### Prequisities

- `make` makes the process automated. Make sure, `make` is installed.
- `docker-compose` and `docker` are used to bake the images and run in isolation. This also helps you from not requiring psql, pgadmin installed in your machine.


#### Steps

1. Clone the repository.
2. Make sure to override `.env` file to add your own variables.
```shell
cp .env.local .env
$EDITOR .env
```

2. Run the project using the following command.
```shell
make dev
```

3. If you're running for the first time, you may want to run migrations with the command.
```shell
make migrate
```

4. If you want to seed the database using the currently provided data, run the following command.
```shell
make seed-db
```

5. The development service will be live: http://localhost:8000

6. PGAdmin will be available on: http://localhost:5000
```

### Credits

- Architecture Inspired from @robusgauli
35 changes: 35 additions & 0 deletions docker-compose.yaml
@@ -0,0 +1,35 @@
version: "3.9"

services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/app
ports:
- "8000:8000"
depends_on:
- db

db:
image: postgres
restart: always
environment:
- POSTGRES_DB=${DB_NAME}
- POSTGRES_USER=${DB_USERNAME}
- POSTGRES_PASSWORD=${DB_PASSWORD}

pgadmin:
restart: always
image: dpage/pgadmin4
environment:
- PGADMIN_DEFAULT_EMAIL=admin@admin.com
- PGADMIN_DEFAULT_PASSWORD=root
ports:
- "5000:80"
depends_on:
- db
logging:
driver: none

3 changes: 3 additions & 0 deletions migrations/__main__.py
@@ -0,0 +1,3 @@
from nepali_dictionary.common.db import migrate

migrate()
35 changes: 0 additions & 35 deletions nepali-dictionary/main.py

This file was deleted.

Empty file added nepali_dictionary/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions nepali_dictionary/common/db/Dictionary.py
@@ -0,0 +1,7 @@
from sqlmodel import Field, SQLModel


class Dictionary(SQLModel, table=True):
word: str = Field(primary_key=True)
kind: str
meaning: str
16 changes: 16 additions & 0 deletions nepali_dictionary/common/db/__init__.py
@@ -0,0 +1,16 @@
from sqlmodel import create_engine, SQLModel

from nepali_dictionary.common.db.Dictionary import Dictionary


engine = create_engine(
'postgresql://root:root@db:5432/db', echo=True)


def migrate():
SQLModel.metadata.create_all(engine)

if __name__ == "__main__":
migrate()

__all__ = ["Dictionary"]
15 changes: 15 additions & 0 deletions nepali_dictionary/core/search/service.py
@@ -0,0 +1,15 @@
import typing as ty

from nepali_dictionary.common.db import Dictionary
from sqlmodel import Session, select


class SearchService:

def search(self, query: str, session: ty.Type[Session], engine) -> ty.Optional[dict]:
with session(engine) as s:
statement = select(Dictionary).where(Dictionary.word == query)
result: ty.Any = s.execute(statement).fetchone()

if result:
return result[0].dict()
18 changes: 18 additions & 0 deletions nepali_dictionary/core/search/views.py
@@ -0,0 +1,18 @@
from fastapi import Depends
from fastapi_utils.cbv import cbv
from fastapi_utils.inferring_router import InferringRouter

from nepali_dictionary.core.search.service import SearchService
from nepali_dictionary.mixins.database import DBMixin

router = InferringRouter()


@cbv(router)
class SearchCBV(DBMixin):
search_service: SearchService = Depends(SearchService)

@router.get("/")
def meaning(self, query: str):
result = self.search_service.search(query, self.session, self.engine)
return {"data" : result}
7 changes: 7 additions & 0 deletions nepali_dictionary/main.py
@@ -0,0 +1,7 @@
from fastapi import FastAPI

from nepali_dictionary.core.search.views import router as search

app = FastAPI()

app.include_router(search, prefix="/search")
9 changes: 9 additions & 0 deletions nepali_dictionary/mixins/database.py
@@ -0,0 +1,9 @@
from starlette.requests import Request
from sqlmodel import Session
from nepali_dictionary.common.db import engine

class DBMixin:
def __init__(self, request: Request):
self.request = request
self.session = Session
self.engine = engine