diff --git a/pizzatool/api.py b/pizzatool/api.py index 9aa6b2f..c40a1ca 100644 --- a/pizzatool/api.py +++ b/pizzatool/api.py @@ -1,7 +1,7 @@ from fastapi import Depends, FastAPI, HTTPException, Response, status from logging import getLogger from ormantic.exceptions import NoMatch -from pizzatool.model import Ingredient +from pizzatool.model import Ingredient, Pizza, PizzaIngredient logger = getLogger(__name__) @@ -20,23 +20,110 @@ async def create_ingredient(name: str, response: Response): return ingredient -async def get_ingredient(id: int): +async def get_ingredient(ingredient_id: int): try: - return await Ingredient.objects.get(id=id) + return await Ingredient.objects.get(id=ingredient_id) except NoMatch: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) -@app.get('/ingredients/{id}') +@app.get('/ingredients/{ingredient_id}') async def read_ingredient(ingredient: Ingredient = Depends(get_ingredient)): return ingredient -@app.put('/ingredients/{id}', status_code=status.HTTP_204_NO_CONTENT) -async def update_ingredient(name: str, ingredient: Ingredient = Depends(get_ingredient)): +@app.put('/ingredients/{ingredient_id}', + status_code=status.HTTP_204_NO_CONTENT) +async def update_ingredient( + name: str, + ingredient: Ingredient = Depends(get_ingredient)): await ingredient.update(name=name) -@app.delete('/ingredients/{id}', status_code=status.HTTP_204_NO_CONTENT) +@app.delete('/ingredients/{ingredient_id}', + status_code=status.HTTP_204_NO_CONTENT) async def delete_ingredient(ingredient: Ingredient = Depends(get_ingredient)): await ingredient.delete() + + +@app.get('/pizzas') +async def read_pizzas(): + return await Pizza.objects.all() + + +@app.post('/pizzas', status_code=status.HTTP_201_CREATED) +async def create_pizza(name: str, response: Response): + pizza = await Pizza.objects.create(name=name) + response.headers['Location'] = 'pizzas/%d' % pizza.id + return pizza + + +async def get_pizza(pizza_id: int): + try: + return await Pizza.objects.get(id=pizza_id) + except NoMatch: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) + + +@app.get('/pizzas/{pizza_id}') +async def read_pizza(pizza: Pizza = Depends(get_pizza)): + return pizza + + +@app.put('/pizzas/{pizza_id}', status_code=status.HTTP_204_NO_CONTENT) +async def update_pizza(name: str, pizza: Pizza = Depends(get_pizza)): + await pizza.update(name=name) + + +@app.delete('/pizzas/{pizza_id}', status_code=status.HTTP_204_NO_CONTENT) +async def delete_pizza(pizza: Pizza = Depends(get_pizza)): + await pizza.delete() + + +@app.get('/pizzas/{pizza_id}/ingredients') +async def read_pizza_ingredients(pizza: Pizza = Depends(get_pizza)): + return await PizzaIngredient.objects.select_related('ingredient') \ + .filter(pizza=pizza).all() + + +@app.post('/pizza/{pizza_id}/ingredients', status_code=status.HTTP_201_CREATED) +async def create_pizza_ingredient( + response: Response, + pizza: Pizza = Depends(get_pizza), + ingredient: Ingredient = Depends(get_ingredient)): + pizza_ingredient = await PizzaIngredient.objects.create( + pizza=pizza, + ingredient=ingredient) + response.headers['Location'] = 'ingredients/%d' % pizza_ingredient.id + return pizza_ingredient + + +async def get_pizza_ingredient( + pizza_ingredient_id: int, + pizza: Pizza = Depends(get_pizza)): + try: + return await PizzaIngredient.objects.select_related('ingredient') \ + .get(id=pizza_ingredient_id, pizza=pizza) + except NoMatch: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) + + +@app.get('/pizzas/{pizza_id}/ingredients/{pizza_ingredient_id}') +async def read_pizza_ingredient( + pizza_ingredient: PizzaIngredient = Depends(get_pizza_ingredient)): + return pizza_ingredient + + +@app.put('/pizzas/{pizza_id}/ingredients/{pizza_ingredient_id}', + status_code=status.HTTP_204_NO_CONTENT) +async def update_pizza_ingredient( + pizza_ingredient: PizzaIngredient = Depends(get_pizza_ingredient), + ingredient: Ingredient = Depends(get_ingredient)): + await pizza_ingredient.update(ingredient=ingredient.id) + + +@app.delete('/pizzas/{pizza_id}/ingredients/{pizza_ingredient_id}', + status_code=status.HTTP_204_NO_CONTENT) +async def delete_pizza_ingredient( + pizza_ingredient: PizzaIngredient = Depends(get_pizza_ingredient)): + await pizza_ingredient.delete() diff --git a/pizzatool/model.py b/pizzatool/model.py index 225d839..5795ef3 100644 --- a/pizzatool/model.py +++ b/pizzatool/model.py @@ -1,5 +1,5 @@ from databases import Database -from ormantic import Integer, Model, Text +from ormantic import Integer, ForeignKey, Model, Text from sqlalchemy import create_engine, MetaData @@ -17,5 +17,26 @@ class Ingredient(Model): database = database +class Pizza(Model): + id: Integer(primary_key=True) = None + name: Text() + + class Mapping: + table_name = 'pizzas' + metadata = metadata + database = database + + +class PizzaIngredient(Model): + id: Integer(primary_key=True) = None + pizza: ForeignKey(Pizza) + ingredient: ForeignKey(Ingredient) + + class Mapping: + table_name = 'pizzaingredients' + metadata = metadata + database = database + + engine = create_engine(str(database.url), echo=True) metadata.create_all(engine)