port recipes over to new schema

This commit is contained in:
Hayden 2021-01-10 20:16:05 -09:00
commit 17537bf43a
5 changed files with 174 additions and 145 deletions

View file

@ -1,45 +1 @@
{
"_default": {
"1": {
"name": "Chicken and Rice With Leeks and Salsa Verde",
"description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.",
"image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg",
"recipeYield": "4 Servings",
"recipeIngredient": [
"1\u00bd lb. skinless, boneless chicken thighs (4\u20138 depending on size)",
"Kosher salt, freshly ground pepper",
"3 Tbsp. unsalted butter, divided",
"2 large or 3 medium leeks, white and pale green parts only, halved lengthwise, thinly sliced",
"Zest and juice of 1 lemon, divided",
"1\u00bd cups long-grain white rice, rinsed until water runs clear",
"2\u00be cups low-sodium chicken broth",
"1 oil-packed anchovy fillet",
"2 garlic cloves",
"1 Tbsp. drained capers",
"Crushed red pepper flakes",
"1 cup tender herb leaves (such as parsley, cilantro, and/or mint)",
"4\u20135 Tbsp. extra-virgin olive oil"
],
"recipeInstructions": [
{
"text": "Season chicken with salt and pepper. Melt 2 Tbsp. butter in a large high-sided skillet over medium-high heat. Add leeks and half of lemon zest, season with salt and pepper, and mix to coat leeks in butter. Reduce heat to medium-low, cover, and cook, stirring occasionally, until leeks are somewhat tender, about 5 minutes. Remove lid, increase heat to medium-high, and cook, stirring occasionally, until tender and just starting to take on color, about 3 minutes. Add rice and cook, stirring often, 3 minutes, then add broth, scraping up any browned bits. Tuck short sides of each chicken thigh underneath so they are touching and nestle seam side down into rice mixture. Bring to a simmer. Cover, reduce heat to medium-low, and cook until rice is tender and chicken is cooked through, about 20 minutes. Remove from heat. Cut remaining 1 Tbsp. butter into small pieces and scatter over mixture. Re-cover and let sit 10 minutes."
},
{
"text": "Meanwhile, pulse anchovy, garlic, capers, a few pinches of red pepper flakes, and remaining lemon zest in a food processor until finely chopped. Add herbs; process until a paste forms. With motor running, gradually stream in oil until loosened to a thick sauce. Add half of lemon juice; season salsa verde with salt."
},
{
"text": "Drizzle remaining lemon juice over chicken and rice. Serve with salsa verde."
}
],
"totalTime": "None",
"slug": "chicken-and-rice-with-leeks-and-salsa-verde",
"categories": [],
"tags": [],
"dateAdded": null,
"notes": [],
"rating": null,
"orgURL": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
"extras": {}
}
}
}
{"_default": {"3": {"name": "Chicken and Rice With Leeks and Salsa Verde", "description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.", "image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg", "recipeYield": "4 Servings", "recipeIngredient": ["1\u00bd lb. skinless, boneless chicken thighs (4\u20138 depending on size)", "Kosher salt, freshly ground pepper", "3 Tbsp. unsalted butter, divided", "2 large or 3 medium leeks, white and pale green parts only, halved lengthwise, thinly sliced", "Zest and juice of 1 lemon, divided", "1\u00bd cups long-grain white rice, rinsed until water runs clear", "2\u00be cups low-sodium chicken broth", "1 oil-packed anchovy fillet", "2 garlic cloves", "1 Tbsp. drained capers", "Crushed red pepper flakes", "1 cup tender herb leaves (such as parsley, cilantro, and/or mint)", "4\u20135 Tbsp. extra-virgin olive oil"], "recipeInstructions": [{"text": "Season chicken with salt and pepper. Melt 2 Tbsp. butter in a large high-sided skillet over medium-high heat. Add leeks and half of lemon zest, season with salt and pepper, and mix to coat leeks in butter. Reduce heat to medium-low, cover, and cook, stirring occasionally, until leeks are somewhat tender, about 5 minutes. Remove lid, increase heat to medium-high, and cook, stirring occasionally, until tender and just starting to take on color, about 3 minutes. Add rice and cook, stirring often, 3 minutes, then add broth, scraping up any browned bits. Tuck short sides of each chicken thigh underneath so they are touching and nestle seam side down into rice mixture. Bring to a simmer. Cover, reduce heat to medium-low, and cook until rice is tender and chicken is cooked through, about 20 minutes. Remove from heat. Cut remaining 1 Tbsp. butter into small pieces and scatter over mixture. Re-cover and let sit 10 minutes."}, {"text": "Meanwhile, pulse anchovy, garlic, capers, a few pinches of red pepper flakes, and remaining lemon zest in a food processor until finely chopped. Add herbs; process until a paste forms. With motor running, gradually stream in oil until loosened to a thick sauce. Add half of lemon juice; season salsa verde with salt."}, {"text": "Drizzle remaining lemon juice over chicken and rice. Serve with salsa verde."}], "totalTime": "None", "slug": "chicken-and-rice-with-leeks-and-salsa-verde", "categories": [], "tags": [], "dateAdded": null, "notes": [], "rating": null, "orgURL": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde", "extras": {}}}}

View file

@ -1,29 +1,30 @@
{
"@context": "http://schema.org",
"@type": "Recipe",
"articleBody": "\u201cAfter a draining day juggling work, homeschooling, and urging children to stop using their masks as slingshots, the ideal food for me isn\u2019t perfectly prepared food that\u2019s been tweezered into position, but a meal that\u2019s simply comforting,\u201d writes the Smitten Kitchen\u2019s Deb Perelman. Right now, it\u2019s this deeply cozy pot of tender chicken thighs, jammy leeks, and broth-soaked rice.",
"alternativeHeadline": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.",
"dateModified": "2021-01-10 15:20:51.422000",
"datePublished": "2020-08-18 04:00:00",
"articleBody": "In this brothy beans recipe, caramelizing fennel, shallots, and lemon builds a base layer that is sweet, tangy, and bright. Tinned sardines add briney flavor (and protein!)\u2014leave them whole or break them up and fold them into the soup. \u00a0And chopped celery or mushrooms work just as well as fennel if you want to swap. This recipe is part of the 2021\u00a0Feel Good Food Plan, our eight-day dinner plan for starting the year off right.",
"alternativeHeadline": "Tinned sardines add briney flavor (and protein!)\u2014leave them whole or break them up and fold them into the soup.",
"dateModified": "2021-01-10 13:22:02.933000",
"datePublished": "2021-01-01 06:00:00",
"keywords": [
"recipes",
"chicken recipes",
"kosher salt",
"black pepper",
"butter",
"leek",
"lemon zest",
"rice",
"chicken broth",
"anchovy",
"garlic",
"capers",
"herb",
"olive oil",
"healthyish",
"fennel",
"lemon",
"olive oil",
"shallot",
"garlic",
"herb",
"white wine",
"chicken broth",
"cannellini beans",
"sardine",
"parsley",
"kosher salt",
"feel good food plan",
"feel good food plan 2021",
"web"
],
"thumbnailUrl": "https://assets.bonappetit.com/photos/5f29796456f43685a49327fb/1:1/w_1125,h_1125,c_limit/Chicken-and-Rice-With-Leeks-Salsa-Verde-01.jpg",
"thumbnailUrl": "https://assets.bonappetit.com/photos/5fdbe3ac045c6b67ead1938c/1:1/w_2880,h_2880,c_limit/BA0221feelgood06_web.jpg",
"publisher": {
"@context": "https://schema.org",
"@type": "Organization",
@ -47,49 +48,58 @@
"author": [
{
"@type": "Person",
"name": "Deb Perelman",
"sameAs": "https://bon-appetit.com/contributor/deb-perelman/"
"name": "Devonn Francis",
"sameAs": "https://bon-appetit.com/contributor/devonn-francis/"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.02,
"ratingCount": 48
"ratingValue": 4.1,
"ratingCount": 12
},
"description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.",
"image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg",
"headline": "Chicken and Rice With Leeks and Salsa Verde",
"name": "Chicken and Rice With Leeks and Salsa Verde",
"description": "Tinned sardines add briney flavor (and protein!)\u2014leave them whole or break them up and fold them into the soup.",
"image": "braised-beans-and-sardines-with-fennel.jpg",
"headline": "Braised Beans and Sardines With Fennel",
"name": "Braised Beans and Sardines With Fennel",
"recipeIngredient": [
"1\u00bd lb. skinless, boneless chicken thighs (4\u20138 depending on size)",
"Kosher salt, freshly ground pepper",
"3 Tbsp. unsalted butter, divided",
"2 large or 3 medium leeks, white and pale green parts only, halved lengthwise, thinly sliced",
"Zest and juice of 1 lemon, divided",
"1\u00bd cups long-grain white rice, rinsed until water runs clear",
"2\u00be cups low-sodium chicken broth",
"1 oil-packed anchovy fillet",
"2 garlic cloves",
"1 Tbsp. drained capers",
"Crushed red pepper flakes",
"1 cup tender herb leaves (such as parsley, cilantro, and/or mint)",
"4\u20135 Tbsp. extra-virgin olive oil"
"1 fennel bulb with fronds, stalks and fronds removed",
"1 lemon, halved",
"\u00bc cup extra-virgin olive oil",
"2 medium shallots, thinly sliced",
"6 garlic cloves, thinly sliced",
"Small handful of mixed hardy herb sprigs (such as bay leaves, thyme, and/or rosemary)",
"\u00bd tsp. crushed red pepper flakes",
"\u00bc cup dry white wine",
"6 cups low-sodium chicken broth",
"2 15-oz. cans cannellini (white kidney) or cranberry beans, rinsed1 4.4-oz. tin oil-packed sardines, drained",
"1 (loosely packed) cup very coarsely chopped parsley",
"Kosher salt",
"Toasted seeded bread (for serving)"
],
"recipeInstructions": [
{
"text": "Season chicken with salt and pepper. Melt 2 Tbsp. butter in a large high-sided skillet over medium-high heat. Add leeks and half of lemon zest, season with salt and pepper, and mix to coat leeks in butter. Reduce heat to medium-low, cover, and cook, stirring occasionally, until leeks are somewhat tender, about 5 minutes. Remove lid, increase heat to medium-high, and cook, stirring occasionally, until tender and just starting to take on color, about 3 minutes. Add rice and cook, stirring often, 3 minutes, then add broth, scraping up any browned bits. Tuck short sides of each chicken thigh underneath so they are touching and nestle seam side down into rice mixture. Bring to a simmer. Cover, reduce heat to medium-low, and cook until rice is tender and chicken is cooked through, about 20 minutes. Remove from heat. Cut remaining 1 Tbsp. butter into small pieces and scatter over mixture. Re-cover and let sit 10 minutes."
"text": "Slice fennel bulb in half lengthwise and cut each half lengthwise into 3 wedges. Thinly slice 1 lemon half into rounds and wriggle out and discard any seeds; leave remaining half intact and set aside."
},
{
"text": "Meanwhile, pulse anchovy, garlic, capers, a few pinches of red pepper flakes, and remaining lemon zest in a food processor until finely chopped. Add herbs; process until a paste forms. With motor running, gradually stream in oil until loosened to a thick sauce. Add half of lemon juice; season salsa verde with salt."
"text": "Heat oil in a medium pot over medium-high. Add fennel, shallots, garlic, hardy herbs, lemon rounds, and red pepper flakes and cook, stirring occasionally, until fennel and lemon are softened slightly and golden brown in spots, 5\u20137 minutes."
},
{
"text": "Drizzle remaining lemon juice over chicken and rice. Serve with salsa verde."
"text": "Using tongs, transfer lemon rounds to a small bowl; set aside. Add wine to pot and cook until reduced by half, about\u00a0 2 minutes. Pour in broth and bring to a boil. Reduce heat to medium-low and simmer, stirring occasionally, until fennel is tender, about 5 minutes. Add beans and simmer until beans soak up some of the broth and are warmed through, 8\u201310 minutes."
},
{
"text": "Meanwhile, working one at a time, slice open each sardine with the tip of a paring knife and remove any visible bones; discard. Separate fillets from one another and place in a small bowl. Squeeze juice from remaining reserved lemon half over fillets."
},
{
"text": "Fish out and discard any hardy herbs and stems you can from braise. Stir in parsley; taste and season broth with more salt if needed."
},
{
"text": "Divide braise among bowls; top with reserved lemon slices and sardines. Serve with bread alongside."
}
],
"recipeYield": "4 Servings",
"url": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
"slug": "chicken-and-rice-with-leeks-and-salsa-verde",
"orgURL": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
"recipeYield": "4 servings",
"url": "https://www.bonappetit.com/recipe/braised-beans-and-sardines-with-fennel",
"slug": "braised-beans-and-sardines-with-fennel",
"orgURL": "https://www.bonappetit.com/recipe/braised-beans-and-sardines-with-fennel",
"categories": [],
"tags": [],
"dateAdded": null,

View file

@ -1,7 +1,9 @@
import json
import mongoengine
from settings import USE_MONGO, USE_TINYDB
from db.mongo.meal_models import MealDocument, MealPlanDocument
from db.mongo.meal_models import MealPlanDocument
from db.mongo.recipe_models import RecipeDocument
from db.mongo.settings_models import SiteSettingsDocument, SiteThemeDocument
from db.tinydb.baseclass import StoreBase
@ -19,6 +21,12 @@ Recipe Actions
- [ ] Query by Category
- [ ] Query by dateAdded
Progress:
- [x] Recipes
- [ ] MealPlans
- [ ] Site Settings
- [ ] Themes
"""
if USE_TINYDB:
@ -38,31 +46,55 @@ class BaseDocument:
self.store: StoreBase
self._document: mongoengine.Document
@staticmethod
def _unpack_mongo(document) -> dict:
document = json.loads(document.to_json())
del document["_id"]
document["dateAdded"] = document["dateAdded"]["$date"]
return document
def get_all(self, limit: int = None, order_by: str = "dateAdded") -> list[dict]:
if USE_MONGO:
documents = self._document.objects.order_by(str(order_by)).limit(limit)
docs = []
for item in documents:
doc = BaseDocument._unpack_mongo(item)
docs.append(doc)
return docs
elif USE_TINYDB:
return self.store.get_all()
def get(self, match_value: str, match_key: str = None, limit=1) -> dict:
if USE_MONGO:
return self._document.objects.get(match_key=match_value).limit(limit)
document = self._document.objects.get(**{str(match_key): match_value})
return BaseDocument._unpack_mongo(document)
elif USE_TINYDB:
return self.store.get(match_value, match_key)
return self.store.get(match_value, match_key, limit=limit)
def save_new(self, document: dict) -> str:
if USE_MONGO:
self._document = self._document(**document)
self._document.save()
return self._document.slug
new_document = self._document(**document)
new_document.save()
return new_document.slug
elif USE_TINYDB:
return self.store.save(document)
def update(self) -> dict:
def delete(self, primary_key) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass
document = self._document.objects.get(
**{str(self.primary_key): primary_key}
)
def delete(self) -> dict:
if USE_MONGO:
pass
if document:
document.delete()
return "Document Deleted"
elif USE_TINYDB:
pass
self.store.delete(primary_key)
class Database:
@ -78,7 +110,42 @@ class Database:
if USE_TINYDB:
self.store = tiny_db.recipes
self._document = RecipeDocument
pass
def update(self, slug: str, new_data: dict) -> None:
if USE_MONGO:
document = self._document.objects.get(slug=slug)
if document:
document.update(set__name=new_data.get("name"))
document.update(set__description=new_data.get("description"))
document.update(set__image=new_data.get("image"))
document.update(set__recipeYield=new_data.get("recipeYield"))
document.update(
set__recipeIngredient=new_data.get("recipeIngredient")
)
document.update(
set__recipeInstructions=new_data.get("recipeInstructions")
)
document.update(set__totalTime=new_data.get("totalTime"))
document.update(set__categories=new_data.get("categories"))
document.update(set__tags=new_data.get("tags"))
document.update(set__notes=new_data.get("notes"))
document.update(set__orgURL=new_data.get("orgURL"))
document.update(set__rating=new_data.get("rating"))
document.update(set__extras=new_data.get("extras"))
document.save()
elif USE_TINYDB:
self.store.update_doc(slug, new_data)
def update_image(self, slug: str, extension: str) -> None:
if USE_MONGO:
document = self._document.objects.get(slug=slug)
if document:
document.update(set__image=f"{slug}.{extension}")
elif USE_TINYDB:
self.store.update_doc(slug, {"image": f"{slug}.{extension}"})
class _Meals(BaseDocument):
def __init__(self) -> None:
@ -86,7 +153,12 @@ class Database:
if USE_TINYDB:
self.store = tiny_db.meals
self.document = MealPlanDocument
pass
def update(self, key: str, new_data: dict) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass
class _Settings(BaseDocument):
def __init__(self) -> None:
@ -94,7 +166,12 @@ class Database:
if USE_TINYDB:
self.store = tiny_db.settings
self.document = SiteSettingsDocument
pass
def update(self, key: str, new_data: dict) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass
class _Themes(BaseDocument):
def __init__(self) -> None:
@ -102,7 +179,12 @@ class Database:
if USE_TINYDB:
self.store = tiny_db.themes
self.document = SiteThemeDocument
pass
def update(self, key: str, new_data: dict) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass
db = Database()

View file

@ -13,16 +13,18 @@ class StoreBase:
if data != []:
raise Exception(
f"Cannot save document. Primary Key: {self.primary_key} already exists"
f"Cannot Save, Primary Key: {self.primary_key} already exists"
)
else:
return self.store.upsert(
document, Query()[self.primary_key] == document[self.primary_key]
)
self.store.insert(document)
return document["slug"]
def delete(self, document_primary_key: str):
self.store.remove(where(self.primary_key) == document_primary_key)
def get_all(self) -> list:
return self.store.all()
def get(self, value: str, key: str = None, limit: int = None) -> list or dict:
"""Retrieves an entry from the database matching the key/value provided.
If no key is provided the classes primary_key will be used instead
@ -49,14 +51,16 @@ class StoreBase:
return data
def update_doc(self, id, document):
data: dict = self.get(self.primary_key, id, limit=1)
data: dict = self.get(id, self.primary_key, limit=1)
if data:
if data[self.primary_key] == document[self.primary_key]:
data.update(document)
return document["slug"]
else:
self.delete(id)
return self.save(document)
self.save(document)
return document["slug"]
elif not data:
raise Exception(

View file

@ -96,9 +96,9 @@ class Recipe(BaseModel):
def get_by_slug(_cls, slug: str):
""" Returns a recipe dictionary from the slug """
document = RecipeDocument.objects.get(slug=slug)
document = db.recipes.get(slug, "slug")
return Recipe._unpack_doc(document)
return document
def save_to_db(self) -> str:
recipe_dict = self.dict()
@ -123,39 +123,16 @@ class Recipe(BaseModel):
def delete(recipe_slug: str) -> str:
""" Removes the recipe from the database by slug """
delete_image(recipe_slug)
document = RecipeDocument.objects.get(slug=recipe_slug)
if document:
document.delete()
return "Document Deleted"
db.recipes.delete(recipe_slug)
return "Document Deleted"
def update(self, recipe_slug: str):
""" Updates the recipe from the database by slug"""
document = RecipeDocument.objects.get(slug=recipe_slug)
if document:
document.update(set__name=self.name)
document.update(set__description=self.description)
document.update(set__image=self.image)
document.update(set__recipeYield=self.recipeYield)
document.update(set__recipeIngredient=self.recipeIngredient)
document.update(set__recipeInstructions=self.recipeInstructions)
document.update(set__totalTime=self.totalTime)
document.update(set__categories=self.categories)
document.update(set__tags=self.tags)
document.update(set__notes=self.notes)
document.update(set__orgURL=self.orgURL)
document.update(set__rating=self.rating)
document.update(set__extras=self.extras)
document.save()
db.recipes.update(recipe_slug, self.dict())
@staticmethod
def update_image(slug: str, extension: str):
document = RecipeDocument.objects.get(slug=slug)
if document:
document.update(set__image=f"{slug}.{extension}")
db.recipes.update_image(slug, extension)
def read_requested_values(keys: list, max_results: int = 0) -> List[dict]:
@ -171,7 +148,7 @@ def read_requested_values(keys: list, max_results: int = 0) -> List[dict]:
"""
recipe_list = []
for recipe in RecipeDocument.objects.order_by("dateAdded").limit(max_results):
for recipe in db.recipes.get_all(limit=max_results, order_by="dateAdded"):
recipe_details = {}
for key in keys:
try: