@an543

Как реализовать на сайте таблицу мер продуктов?

Подскажите, как реализовать на сайте таблицу калорийности и единиц мер ингредиентов питания с пересчетом. Пересчет из грамм в ст.л. например. Для начала я так понял создать таблицу типа 1-гр 2-кг 3 -ст.л 4 дес.л 5 -стакан ... 13-шт. Далее таблица ингредиентов ккал/100гр: 1-мука - 220ккал, 2-молоко- 550ккал .... Подскажите как связать это все при условии, что не все единицы подходят к ингредиентам( напимер к молоку шт. нельзя применить, а к банану мл.)т
  • Вопрос задан
  • 122 просмотра
Пригласить эксперта
Ответы на вопрос 1
neatsoft
@neatsoft
Life is too short for bad software
Для каждого продукта питания необходимо хранить калорийность в пересчете на грамм, а для единиц измерения указывать вес в граммах:

5c8901b18f654618880623.png

Единицы измерения не имеют смысла безотносительно продуктов питания, т.к. между десятком яиц, столовой ложкой муки, и одним бананом среднего размера (200 гр с кожурой, 150 гр мякоти) нет ничего общего.

Пример реализации на Django:

models.py
import decimal

from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models


class Foodstuff(models.Model):
    name = models.CharField(max_length=200)
    kcal_per_gram = models.DecimalField(
        # the most calorie-dense food is fat cattle - 925 kcal per 100 gram (9.25 kcal/gram)
        max_digits=3,
        decimal_places=2,
        validators=[
            MaxValueValidator(decimal.Decimal('9.99')),
            MinValueValidator(decimal.Decimal('0.00')),
        ],
    )

    @property
    def kcal_per_100_gram(self):
        return int(self.kcal_per_gram * 100)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['name']


class FoodstuffUnit(models.Model):
    foodstuff = models.ForeignKey(
        Foodstuff,
        models.CASCADE,
    )
    name = models.CharField(max_length=200)
    net_weight = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        validators=[
            MinValueValidator(decimal.Decimal('0.01')),
        ],
    )

    @property
    def kcal(self):
        return int(self.foodstuff.kcal_per_gram * self.net_weight)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['name']
        unique_together = ('foodstuff', 'name')


class Dish(models.Model):
    name = models.CharField(max_length=200)

    @property
    def kcal(self):
        return sum(i.kcal for i in self.dishingredient_set.all())

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['name']
        verbose_name_plural = 'dishes'


class DishIngredient(models.Model):
    dish = models.ForeignKey(
        Dish,
        models.CASCADE,
    )
    foodstuff = models.ForeignKey(
        Foodstuff,
        models.PROTECT,
    )
    foodstuff_unit = models.ForeignKey(
        FoodstuffUnit,
        models.PROTECT,
        blank=True,
        null=True,
    )
    amount = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        validators=[
            MinValueValidator(decimal.Decimal('0.00')),
        ],
    )

    @property
    def kcal(self):
        weight = self.amount
        if self.foodstuff_unit is not None:
            weight *= self.foodstuff_unit.net_weight
        return int(self.foodstuff.kcal_per_gram * weight)

    def __str__(self):
        unit = 'гр' if self.foodstuff_unit is None else f'{self.foodstuff_unit}'
        return f'{self.dish}: {self.foodstuff}, {unit} - {self.amount}'

    class Meta:
        ordering = ['id']


admin.py
from django.contrib import admin

from . import models as app_models


class FoodstuffUnitInline(admin.TabularInline):
    model = app_models.FoodstuffUnit
    extra = 0
    readonly_fields = (
        'kcal',
    )


@admin.register(app_models.Foodstuff)
class FoodstuffAdmin(admin.ModelAdmin):
    list_display = (
        'name',
        'kcal_per_100_gram',
    )
    inlines = (
        FoodstuffUnitInline,
    )
    readonly_fields = (
        'kcal_per_100_gram',
    )


class DishIngredientInline(admin.TabularInline):
    model = app_models.DishIngredient
    extra = 0
    readonly_fields = (
        'kcal',
    )


@admin.register(app_models.Dish)
class DishAdmin(admin.ModelAdmin):
    list_display = (
        'name',
        'kcal',
    )
    inlines = (
        DishIngredientInline,
    )
    readonly_fields = (
        'kcal',
    )
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы