dsite/recipe/models.py
Ching d16cfa0ca2 feat(recipe views): 增加菜谱原材料统计接口
增加菜谱原材料统计接口

Signed-off-by: Ching <loooching@gmail.com>
2022-02-27 19:41:45 +08:00

248 lines
8.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import random
from django.db import models
from django.utils.timezone import now, localtime
import datetime
from utils import const
import utils
class Ingredient(models.Model):
name = models.CharField(max_length=128)
unit = models.CharField(max_length=32)
status = models.CharField(max_length=32, default=const.INGREDIENT_STATUS_ACTIVE)
class RecipeIngredient(models.Model):
recipe = models.ForeignKey('Recipe', on_delete=models.CASCADE, related_name='recipe_ingredients')
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE, related_name='recipe_ingredients')
status = models.CharField(max_length=32, default=const.INGREDIENT_STATUS_ACTIVE)
quantity = models.FloatField()
def serialize(self):
return {
'id': self.id,
'recipe': {'id': self.recipe.id, 'name': self.recipe.name},
'ingredient': {'id': self.ingredient.id, 'name': self.ingredient.name, 'unit': self.ingredient.unit},
'quantity': self.quantity,
}
class Recipe(models.Model):
name = models.CharField(max_length=128)
recipe_type = models.CharField(max_length=32, default=const.RECIPE_TYPE_MEAT)
status = models.CharField(max_length=32, default=const.RECIPE_STATUS_ACTIVE)
note = models.TextField(null=True)
rate = models.IntegerField(default=0)
difficulty = models.IntegerField(default=0)
def serialize(self, verbose=False):
data = {'id': self.id, 'name': self.name, 'recipe_type': self.recipe_type}
if verbose:
data.update(
{
'difficulty': self.difficulty,
'rate': self.rate,
'note': self.note,
'recipe_ingredients': self.get_ingredients(),
}
)
return data
def get_ingredients(self):
return [i.serialize() for i in self.recipeingredient_set.order_by('id')]
@classmethod
def create_from_str(cls, content):
content = content.strip()
if not content:
return
name, *data = content.split(' ')
recipe_type = rate = difficulty = None
keys = [recipe_type, rate, difficulty]
for x in range(len(data)):
keys[x] = data[x]
recipe_type, rate, difficulty = keys
if recipe_type == '':
recipe_type = const.RECIPE_TYPE_MEAT
elif recipe_type == '':
recipe_type = const.RECIPE_TYPE_VEGETABLE
elif recipe_type == '':
recipe_type = const.RECIPE_TYPE_SOUP
else:
recipe_type = const.RECIPE_TYPE_MEAT
if rate:
try:
rate = int(rate)
except:
rate = 0
else:
rate = 0
if difficulty:
try:
difficulty = int(difficulty)
except:
difficulty = 0
else:
difficulty = 0
recipe = cls.objects.create(
name=name, recipe_type=recipe_type, rate=rate, difficulty=difficulty, status=const.RECIPE_STATUS_ACTIVE
)
return recipe
@property
def display_recipe_type(self):
if self.recipe_type == const.RECIPE_TYPE_VEGETABLE:
return ''
elif self.recipe_type == const.RECIPE_TYPE_MEAT:
return ''
elif self.recipe_type == const.RECIPE_TYPE_SOUP:
return ''
return ''
@property
def display_rate(self):
return '🍚' * self.rate
@property
def display_difficult(self):
return '⭐️' * self.difficulty
def construct_lart_card(self):
data = {
"config": {"wide_screen_mode": True},
"header": {"title": {"tag": "plain_text", "content": self.name}, "template": "blue"},
"elements": [
{
"tag": "markdown",
"content": "**类型**%s\n**评分**%s\n**难度**%s"
% (self.display_recipe_type, self.display_rate, self.display_difficult),
},
{
"tag": "action",
"actions": [
{
"tag": "button",
"text": {"tag": "plain_text", "content": "查看"},
"multi_url": {
"url": "https://recipe.tunpok.com/recipe/%s" % self.id,
"android_url": "https://recipe.tunpok.com/recipe-mobile/recipe/%s" % self.id,
"ios_url": "https://recipe.tunpok.com/recipe-mobile/recipe/%s" % self.id,
"pc_url": "https://recipe.tunpok.com/recipe/%s" % self.id,
},
"type": "primary",
},
{"tag": "button", "text": {"tag": "plain_text", "content": "删除"}, "type": "danger"},
],
},
],
}
return data
@classmethod
def sum_recipe_ingredients(cls, recipe_ids):
data = {}
for recipe_id in recipe_ids:
recipe = cls.objects.get(id=recipe_id)
recipe_ingredients = RecipeIngredient.objects.filter(recipe=recipe)
for ingredient in recipe_ingredients:
if not ingredient.ingredient.id in data:
data[ingredient.ingredient.id] = {
'name': ingredient.ingredient.name,
'quantity': 0,
'unit': ingredient.ingredient.unit,
}
data[ingredient.ingredient.id]['quantity'] += ingredient.quantity
return data
class DailyRecipe(models.Model):
recipes = models.ManyToManyField(Recipe)
date = models.DateField()
meal_type = models.CharField(max_length=32, default=const.DAILY_RECIPE_MEAL_TYPE_SUPPER)
def generate_recipe(self, prev_recipes=None, ignore_prev=False):
if not prev_recipes:
prev_recipes = []
if ignore_prev:
prev_recipes = []
recipes = []
retry = 5
# meat
for x in range(0, 2):
while True:
recipe = (
Recipe.objects.filter(recipe_type=const.RECIPE_TYPE_MEAT)
.exclude(status=const.RECIPE_STATUS_DELETED)
.order_by('?')
.first()
)
if recipe and recipe.id not in recipes and recipe.id not in prev_recipes:
recipes.append(recipe.id)
break
else:
retry -= 1
if retry <= 0:
retry = 5
break
# vegetable
for x in range(0, 1):
while True:
recipe = (
Recipe.objects.filter(recipe_type=const.RECIPE_TYPE_VEGETABLE)
.exclude(status=const.RECIPE_STATUS_DELETED)
.order_by('?')
.first()
)
if recipe and recipe.id not in recipes and recipe.id not in prev_recipes:
recipes.append(recipe.id)
break
else:
retry -= 1
if retry <= 0:
retry = 5
break
# soup
if random.randint(0, 2):
recipe = (
Recipe.objects.filter(recipe_type=const.RECIPE_TYPE_SOUP)
.exclude(status=const.RECIPE_STATUS_DELETED)
.order_by('?')
.first()
)
# if recipe not in recipes and recipe not in prev_recipes:
if recipe:
recipes.append(recipe.id)
self.recipes.set(Recipe.objects.filter(id__in=recipes))
def serialize(self):
data = {const.RECIPE_TYPE_MEAT: [], const.RECIPE_TYPE_VEGETABLE: [], const.RECIPE_TYPE_SOUP: []}
for key_, value_ in data.items():
for recipe in self.recipes.filter(recipe_type=key_).order_by('id'):
value_.append(recipe.serialize())
date = now()
date = date.replace(year=self.date.year, month=self.date.month, day=self.date.day, hour=0, minute=0)
data['date'] = utils.timestamp_of(utils.day_start(date))
data['id'] = self.id
return data
@classmethod
def get_week_recipe_data(cls):
today = localtime()
week_start = (today - datetime.timedelta(days=today.weekday())).date()
week_end = week_start + datetime.timedelta(days=6)
daily_recipes = cls.objects.filter(date__gte=week_start, date__lte=week_end).order_by('date')
data = [{}] * (7 - len(daily_recipes))
for daily_recipe in daily_recipes:
data.append(daily_recipe.serialize())
return data