Added relational database support and simple models.

This commit is contained in:
Kamil 2021-11-19 23:42:28 +01:00
parent 541abcb3b9
commit 8e208e2f99
10 changed files with 169 additions and 11 deletions

View File

@ -1,3 +1,4 @@
HOST=<IP or hostname>
PORT=<port number>
ENV=<dev or prod>
ENV=<dev or prod>
SQLALCHEMY_DATABASE_URL=<file location>

5
.gitignore vendored
View File

@ -139,4 +139,7 @@ dmypy.json
cython_debug/
# PyCharm
.idea/
.idea/
# SQLite3
*.db

View File

@ -7,3 +7,5 @@ load_dotenv()
HOST = os.getenv('HOST')
PORT = int(os.getenv('PORT'))
ENV = os.getenv('ENV')
SQLALCHEMY_DATABASE_URL = os.getenv('SQLALCHEMY_DATABASE_URL')

0
db/__init__.py Normal file
View File

35
db/crud.py Normal file
View File

@ -0,0 +1,35 @@
from sqlalchemy.orm import Session
from . import models, schemas
def get_owner(db: Session, owner_id: int):
return db.query(models.Owner).filter(models.Owner.id == owner_id).first()
def get_owner_by_name(db: Session, name: str):
return db.query(models.Owner).filter(models.Owner.name == name).first()
def get_owners(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.Owner).offset(skip).limit(limit).all()
def create_owner(db: Session, owner: schemas.OwnerIn):
db_owner = models.Owner(name=owner.name)
db.add(db_owner)
db.commit()
db.refresh(db_owner)
return db_owner
def get_readings(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.Reading).offset(skip).limit(limit).all()
def create_owner_reading(db: Session, reading: schemas.ReadingIn, owner_id: int):
db_reading = models.Reading(**reading.dict(), owner_id=owner_id)
db.add(db_reading)
db.commit()
db.refresh(db_reading)
return db_reading

14
db/database.py Normal file
View File

@ -0,0 +1,14 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import config
engine = create_engine(
config.SQLALCHEMY_DATABASE_URL,
connect_args={'check_same_thread': False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

25
db/models.py Normal file
View File

@ -0,0 +1,25 @@
from sqlalchemy import Boolean, Column, DateTime, Float, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from .database import Base
class Owner(Base):
__tablename__ = 'owners'
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True, index=True)
is_active = Column(Boolean, default=True)
readings = relationship('Reading', back_populates='owner_system')
class Reading(Base):
__tablename__ = 'readings'
id = Column(Integer, primary_key=True, index=True)
timestamp = Column(DateTime, unique=True)
temperature = Column(Float, default=10.0)
owner_id = Column(Integer, ForeignKey('owners.id'))
owner_system = relationship('Owner', back_populates='readings')

38
db/schemas.py Normal file
View File

@ -0,0 +1,38 @@
from datetime import datetime
from typing import List
from pydantic import BaseModel
class ReadingBase(BaseModel):
timestamp: datetime
temperature: float
class ReadingIn(ReadingBase):
pass
class Reading(ReadingBase):
id: int
owner_id: int
class Config:
orm_mode = True
class OwnerBase(BaseModel):
name: str
class OwnerIn(OwnerBase):
pass
class Owner(OwnerBase):
id: int
is_active: bool
readings: List[Reading] = []
class Config:
orm_mode = True

54
main.py
View File

@ -1,20 +1,58 @@
from typing import List
import uvicorn
from fastapi import FastAPI
from fastapi.responses import PlainTextResponse
from fastapi import Depends, FastAPI, HTTPException, status
from sqlalchemy.orm import Session
import config
from db import crud, models, schemas
from db.database import SessionLocal, engine
models.Base.metadata.create_all(bind=engine)
app = FastAPI()
@app.get('/')
async def index():
return {'Hello': 'World'}
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get('/text', response_class=PlainTextResponse)
async def text():
return 'Hello, World!'
@app.post('/owners/', response_model=schemas.Owner)
def create_owner(owner: schemas.OwnerIn, db: Session = Depends(get_db)):
db_owner = crud.get_owner_by_name(db, name=owner.name)
if db_owner:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Owner already exists.')
return crud.create_owner(db=db, owner=owner)
@app.get('/owners/', response_model=List[schemas.Owner])
def read_owners(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
owners = crud.get_owners(db, skip=skip, limit=limit)
return owners
@app.get('/owners/{owner_id}', response_model=schemas.Owner)
def read_owner(owner_id: int, db: Session = Depends(get_db)):
db_owner = crud.get_owner(db, owner_id=owner_id)
if not db_owner:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='Owner not found.')
return db_owner
@app.post('/owners/{owner_id}/readings/', response_model=schemas.Reading)
def create_reading_for_owner(owner_id: int, reading: schemas.ReadingIn, db: Session = Depends(get_db)):
return crud.create_owner_reading(db=db, reading=reading, owner_id=owner_id)
@app.get('/readings/', response_model=List[schemas.Reading])
def read_readings(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
readings = crud.get_readings(db, skip=skip, limit=limit)
return readings
if __name__ == '__main__':
reload = config.ENV == 'dev'

View File

@ -1,3 +1,5 @@
uvicorn~=0.15.0
fastapi~=0.70.0
python-dotenv~=0.19.2
python-dotenv~=0.19.2
SQLAlchemy~=1.4.27
pydantic~=1.8.2