db and models for comments

This commit is contained in:
hay-kot 2021-05-29 19:08:46 -08:00
commit 4a9f2638f4
10 changed files with 146 additions and 4 deletions

View file

@ -5,6 +5,7 @@ from mealie.db.db_base import BaseDocument
from mealie.db.models.event import Event, EventNotification
from mealie.db.models.group import Group
from mealie.db.models.mealplan import MealPlan
from mealie.db.models.recipe.comment import RecipeComment
from mealie.db.models.recipe.recipe import Category, RecipeModel, Tag
from mealie.db.models.settings import CustomPage, SiteSettings
from mealie.db.models.shopping_list import ShoppingList
@ -12,6 +13,7 @@ from mealie.db.models.sign_up import SignUp
from mealie.db.models.theme import SiteThemeModel
from mealie.db.models.users import LongLiveToken, User
from mealie.schema.category import RecipeCategoryResponse, RecipeTagResponse
from mealie.schema.comments import CommentOut
from mealie.schema.event_notifications import EventNotificationIn
from mealie.schema.events import Event as EventSchema
from mealie.schema.meal import MealPlanOut
@ -110,6 +112,13 @@ class _Users(BaseDocument):
return self.schema.from_orm(entry)
class _Comments(BaseDocument):
def __init__(self) -> None:
self.primary_key = "id"
self.sql_model = RecipeComment
self.schema = CommentOut
class _LongLiveToken(BaseDocument):
def __init__(self) -> None:
self.primary_key = "id"
@ -190,6 +199,7 @@ class Database:
self.events = _Events()
self.event_notifications = _EventNotification()
self.shopping_lists = _ShoppingList()
self.comments = _Comments()
db = Database()

View file

@ -8,6 +8,7 @@ class BaseMixins:
def update(self, *args, **kwarg):
self.__init__(*args, **kwarg)
@classmethod
def get_ref(cls_type, session: Session, match_value: str, match_attr: str = "id"):
eff_ref = getattr(cls_type, match_attr)
return session.query(cls_type).filter(eff_ref == match_value).one_or_none()

View file

@ -16,7 +16,6 @@ class RecipeAsset(SqlAlchemyBase):
icon=None,
file_name=None,
) -> None:
print("Asset Saved", name)
self.name = name
self.file_name = file_name
self.icon = icon

View file

@ -0,0 +1,25 @@
from datetime import datetime
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
from mealie.db.models.recipe.recipe import RecipeModel
from mealie.db.models.users import User
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, orm
class RecipeComment(SqlAlchemyBase, BaseMixins):
__tablename__ = "recipe_comments"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey("recipes.id"))
recipe = orm.relationship("RecipeModel", back_populates="comments")
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
user = orm.relationship("User", back_populates="comments", single_parent=True, foreign_keys=[user_id])
date_added = Column(DateTime, default=datetime.now)
text = Column(String)
def __init__(self, recipe_slug, user, text, session, **_) -> None:
self.text = text
self.user = User.get_ref(session, user)
self.recipe = RecipeModel.get_ref(session, recipe_slug, "slug")
def update(self, text, **_) -> None:
self.text = text

View file

@ -55,6 +55,8 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
collection_class=ordering_list("position"),
)
comments: list = orm.relationship("RecipeComment", back_populates="recipe", cascade="all, delete, delete-orphan")
# Mealie Specific
slug = sa.Column(sa.String, index=True, unique=True)
settings = orm.relationship("RecipeSettings", uselist=False, cascade="all, delete-orphan")

View file

@ -33,6 +33,10 @@ class User(SqlAlchemyBase, BaseMixins):
LongLiveToken, back_populates="user", cascade="all, delete, delete-orphan", single_parent=True
)
comments: list = orm.relationship(
"RecipeComment", back_populates="user", cascade="all, delete, delete-orphan", single_parent=True
)
favorite_recipes: list[RecipeModel] = orm.relationship(RecipeModel, back_populates="favorited_by")
def __init__(
@ -56,7 +60,7 @@ class User(SqlAlchemyBase, BaseMixins):
self.password = password
self.favorite_recipes = [
RecipeModel.get_ref(RecipeModel, session=session, match_value=x, match_attr="slug")
RecipeModel.get_ref(session=session, match_value=x, match_attr="slug")
for x in favorite_recipes
]
@ -78,7 +82,7 @@ class User(SqlAlchemyBase, BaseMixins):
self.password = password
self.favorite_recipes = [
RecipeModel.get_ref(RecipeModel, session=session, match_value=x, match_attr="slug")
RecipeModel.get_ref(session=session, match_value=x, match_attr="slug")
for x in favorite_recipes
]

View file

@ -1,5 +1,5 @@
from fastapi import APIRouter
from mealie.routes.recipe import all_recipe_routes, category_routes, recipe_crud_routes, tag_routes
from mealie.routes.recipe import all_recipe_routes, category_routes, comments, recipe_crud_routes, tag_routes
recipe_router = APIRouter()
@ -7,3 +7,4 @@ recipe_router.include_router(all_recipe_routes.router)
recipe_router.include_router(recipe_crud_routes.router)
recipe_router.include_router(category_routes.router)
recipe_router.include_router(tag_routes.router)
recipe_router.include_router(comments.router)

View file

@ -0,0 +1,54 @@
from http.client import HTTPException
from fastapi import APIRouter, Depends, status
from mealie.db.database import db
from mealie.db.db_setup import generate_session
from mealie.routes.deps import get_current_user
from mealie.schema.comments import CommentIn, CommentOut, CommentSaveToDB
from mealie.schema.user import UserInDB
from sqlalchemy.orm.session import Session
router = APIRouter(prefix="/api", tags=["Recipe Comments"])
@router.post("/recipes/{slug}/comments")
async def create_comment(
slug: str,
new_comment: CommentIn,
session: Session = Depends(generate_session),
current_user: UserInDB = Depends(get_current_user),
):
""" Create comment in the Database """
new_comment = CommentSaveToDB(user=current_user.id, text=new_comment.text, recipe_slug=slug)
return db.comments.create(session, new_comment)
@router.put("/recipes/{slug}/comments/{id}")
async def update_comment(
id: int,
new_comment: CommentIn,
session: Session = Depends(generate_session),
current_user: UserInDB = Depends(get_current_user),
):
""" Update comment in the Database """
old_comment: CommentOut = db.comments.get(session, id)
if current_user.id != old_comment.user.id:
raise HTTPException(status.HTTP_401_UNAUTHORIZED)
return db.comments.update(session, id, new_comment)
@router.delete("/recipes/{slug}/comments/{id}")
async def delete_comment(
id: int, session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)
):
""" Delete comment from the Database """
comment: CommentOut = db.comments.get(session, id)
print(current_user.id, comment.user.id, current_user.admin)
if current_user.id == comment.user.id or current_user.admin:
db.comments.delete(session, id)
return
raise HTTPException(status.HTTP_401_UNAUTHORIZED)

43
mealie/schema/comments.py Normal file
View file

@ -0,0 +1,43 @@
from datetime import datetime
from typing import Optional
from fastapi_camelcase import CamelModel
from pydantic.utils import GetterDict
class UserBase(CamelModel):
id: int
username: Optional[str]
admin: bool
class Config:
orm_mode = True
class CommentIn(CamelModel):
text: str
class CommentSaveToDB(CommentIn):
recipe_slug: str
user: int
class Config:
orm_mode = True
class CommentOut(CommentIn):
id: int
recipe_slug: str
date_added: datetime
user: UserBase
class Config:
orm_mode = True
@classmethod
def getter_dict(_cls, name_orm):
return {
**GetterDict(name_orm),
"recipe_slug": name_orm.recipe.slug,
}

View file

@ -5,6 +5,7 @@ from typing import Any, Optional
from fastapi_camelcase import CamelModel
from mealie.core.config import app_dirs
from mealie.db.models.recipe.recipe import RecipeModel
from mealie.schema.comments import CommentOut
from pydantic import BaseModel, Field, validator
from pydantic.utils import GetterDict
from slugify import slugify
@ -102,6 +103,8 @@ class Recipe(RecipeSummary):
org_url: Optional[str] = Field(None, alias="orgURL")
extras: Optional[dict] = {}
comments: Optional[list[CommentOut]] = []
@staticmethod
def directory_from_slug(slug) -> Path:
return app_dirs.RECIPE_DATA_DIR.joinpath(slug)