cleanup migrations, remove pint to speed up base conversion and calculate properties on converted ingredients
This commit is contained in:
@ -160,7 +160,8 @@ class OpenDataImporter:
|
||||
update_list.append(Food(id=existing_food_id, open_data_slug=k, ))
|
||||
|
||||
Food.load_bulk(insert_list, None)
|
||||
Food.objects.bulk_update(update_list, update_field_list)
|
||||
if len(update_list) > 0:
|
||||
Food.objects.bulk_update(update_list, update_field_list)
|
||||
|
||||
self._update_slug_cache(Food, 'food')
|
||||
|
||||
|
@ -33,7 +33,7 @@ class FoodPropertyHelper:
|
||||
uch = UnitConversionHelper(self.space)
|
||||
|
||||
for i in ingredients:
|
||||
conversions = [i] # uch.get_conversions(i)
|
||||
conversions = uch.get_conversions(i)
|
||||
for pt in property_types:
|
||||
found_property = False
|
||||
for p in i.food.foodproperty_set.all():
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django.core.cache import caches
|
||||
from pint import UnitRegistry, UndefinedUnitError, PintError
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
from cookbook.helper.cache_helper import CacheHelper
|
||||
from cookbook.models import Ingredient, Unit
|
||||
|
||||
@ -12,6 +13,38 @@ CONVERT_TO_UNITS = {
|
||||
'uk': ['ounce', 'pound', 'imperial_fluid_ounce', 'imperial_pint', 'imperial_quart', 'imperial_gallon'],
|
||||
}
|
||||
|
||||
CONVERSION_TABLE = {
|
||||
'weight': {
|
||||
'g': 1000,
|
||||
'kg': 1,
|
||||
'ounce': 35.274,
|
||||
'pound': 2.20462
|
||||
},
|
||||
'volume': {
|
||||
'ml': 1000,
|
||||
'l': 1,
|
||||
'fluid_ounce': 33.814,
|
||||
'pint': 2.11338,
|
||||
'quart': 1.05669,
|
||||
'gallon': 0.264172,
|
||||
'tbsp': 67.628,
|
||||
'tsp': 202.884,
|
||||
'imperial_fluid_ounce': 35.1951,
|
||||
'imperial_pint': 1.75975,
|
||||
'imperial_quart': 0.879877,
|
||||
'imperial_gallon': 0.219969,
|
||||
'imperial_tbsp': 56.3121,
|
||||
'imperial_tsp': 168.936,
|
||||
},
|
||||
}
|
||||
|
||||
BASE_UNITS_WEIGHT = CONVERSION_TABLE['weight'].keys()
|
||||
BASE_UNITS_VOLUME = CONVERSION_TABLE['volume'].keys()
|
||||
|
||||
|
||||
class ConversionException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class UnitConversionHelper:
|
||||
space = None
|
||||
@ -23,6 +56,19 @@ class UnitConversionHelper:
|
||||
"""
|
||||
self.space = space
|
||||
|
||||
@staticmethod
|
||||
def convert_from_to(from_unit, to_unit, amount):
|
||||
system = None
|
||||
if from_unit in BASE_UNITS_WEIGHT and to_unit in BASE_UNITS_WEIGHT:
|
||||
system = 'weight'
|
||||
if from_unit in BASE_UNITS_VOLUME and to_unit in BASE_UNITS_VOLUME:
|
||||
system = 'volume'
|
||||
|
||||
if not system:
|
||||
raise ConversionException('Trying to convert units not existing or not in one unit system (weight/volume)')
|
||||
|
||||
return Decimal(amount / Decimal(CONVERSION_TABLE[system][from_unit] / CONVERSION_TABLE[system][to_unit]))
|
||||
|
||||
def base_conversions(self, ingredient_list):
|
||||
"""
|
||||
Calculates all possible base unit conversions for each ingredient give.
|
||||
@ -31,14 +77,12 @@ class UnitConversionHelper:
|
||||
:param ingredient_list: list of ingredients to convert
|
||||
:return: ingredient list with appended conversions
|
||||
"""
|
||||
ureg = UnitRegistry()
|
||||
pint_converted_list = ingredient_list.copy()
|
||||
base_conversion_ingredient_list = ingredient_list.copy()
|
||||
for i in ingredient_list:
|
||||
try:
|
||||
conversion_unit = i.unit.name
|
||||
if i.unit.base_unit:
|
||||
conversion_unit = i.unit.base_unit
|
||||
quantitiy = ureg.Quantity(f'{i.amount} {conversion_unit}')
|
||||
|
||||
# TODO allow setting which units to convert to? possibly only once conversions become visible
|
||||
units = caches['default'].get(CacheHelper(self.space).BASE_UNITS_CACHE_KEY, None)
|
||||
@ -48,16 +92,15 @@ class UnitConversionHelper:
|
||||
|
||||
for u in units:
|
||||
try:
|
||||
converted = quantitiy.to(u.base_unit)
|
||||
ingredient = Ingredient(amount=Decimal(converted.m), unit=u, food=ingredient_list[0].food, )
|
||||
if not any((x.unit.name == ingredient.unit.name or x.unit.base_unit == ingredient.unit.name) for x in pint_converted_list):
|
||||
pint_converted_list.append(ingredient)
|
||||
except PintError:
|
||||
ingredient = Ingredient(amount=self.convert_from_to(conversion_unit, u.base_unit, i.amount), unit=u, food=ingredient_list[0].food, )
|
||||
if not any((x.unit.name == ingredient.unit.name or x.unit.base_unit == ingredient.unit.name) for x in base_conversion_ingredient_list):
|
||||
base_conversion_ingredient_list.append(ingredient)
|
||||
except ConversionException:
|
||||
pass
|
||||
except PintError:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return pint_converted_list
|
||||
return base_conversion_ingredient_list
|
||||
|
||||
def get_conversions(self, ingredient):
|
||||
"""
|
||||
@ -94,21 +137,5 @@ class UnitConversionHelper:
|
||||
if uc.food is None or uc.food == food:
|
||||
if unit == uc.base_unit:
|
||||
return Ingredient(amount=amount * (uc.converted_amount / uc.base_amount), unit=uc.converted_unit, food=food, space=self.space)
|
||||
# return {
|
||||
# 'amount': amount * (uc.converted_amount / uc.base_amount),
|
||||
# 'unit': {
|
||||
# 'id': uc.converted_unit.id,
|
||||
# 'name': uc.converted_unit.name,
|
||||
# 'plural_name': uc.converted_unit.plural_name
|
||||
# },
|
||||
# }
|
||||
else:
|
||||
return Ingredient(amount=amount * (uc.base_amount / uc.converted_amount), unit=uc.base_unit, food=food, space=self.space)
|
||||
# return {
|
||||
# 'amount': amount * (uc.base_amount / uc.converted_amount),
|
||||
# 'unit': {
|
||||
# 'id': uc.base_unit.id,
|
||||
# 'name': uc.base_unit.name,
|
||||
# 'plural_name': uc.base_unit.plural_name
|
||||
# },
|
||||
# }
|
||||
|
@ -0,0 +1,181 @@
|
||||
# Generated by Django 4.1.7 on 2023-05-06 19:16
|
||||
|
||||
import cookbook.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django_prometheus.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cookbook', '0188_space_no_sharing_limit'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='FoodProperty',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('food_amount', models.DecimalField(decimal_places=2, default=0, max_digits=32)),
|
||||
('property_amount', models.DecimalField(decimal_places=4, default=0, max_digits=32)),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PropertyType',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('unit', models.CharField(blank=True, max_length=64, null=True)),
|
||||
('icon', models.CharField(blank=True, max_length=16, null=True)),
|
||||
('description', models.CharField(blank=True, max_length=512, null=True)),
|
||||
('category', models.CharField(blank=True, choices=[('NUTRITION', 'Nutrition'), ('ALLERGEN', 'Allergen'), ('PRICE', 'Price'), ('GOAL', 'Goal'), ('OTHER', 'Other')], max_length=64, null=True)),
|
||||
('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='RecipeProperty',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('property_amount', models.DecimalField(decimal_places=4, default=0, max_digits=32)),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UnitConversion',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('base_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)),
|
||||
('converted_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)),
|
||||
],
|
||||
bases=(django_prometheus.models.ExportModelOperationsMixin('unit_conversion'), models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='fdc_id',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='preferred_shopping_unit',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_shopping_unit', to='cookbook.unit'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='preferred_unit',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_unit', to='cookbook.unit'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='supermarket',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='supermarketcategory',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unit',
|
||||
name='base_unit',
|
||||
field=models.TextField(blank=True, default=None, max_length=256, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unit',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='supermarketcategoryrelation',
|
||||
constraint=models.UniqueConstraint(fields=('supermarket', 'category'), name='unique_sm_category_relation'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unitconversion',
|
||||
name='base_unit',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_base_relation', to='cookbook.unit'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unitconversion',
|
||||
name='converted_unit',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_converted_relation', to='cookbook.unit'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unitconversion',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unitconversion',
|
||||
name='food',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.food'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unitconversion',
|
||||
name='space',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='recipeproperty',
|
||||
name='property_type',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.propertytype'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='recipeproperty',
|
||||
name='space',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='propertytype',
|
||||
name='space',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='foodproperty',
|
||||
name='food',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.food'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='foodproperty',
|
||||
name='food_unit',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.unit'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='foodproperty',
|
||||
name='property_type',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.propertytype'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='foodproperty',
|
||||
name='space',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='recipe',
|
||||
name='properties',
|
||||
field=models.ManyToManyField(blank=True, to='cookbook.recipeproperty'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='unitconversion',
|
||||
constraint=models.UniqueConstraint(fields=('space', 'base_unit', 'converted_unit', 'food'), name='f_unique_conversion_per_space'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='propertytype',
|
||||
constraint=models.UniqueConstraint(fields=('space', 'name'), name='property_type_unique_name_per_space'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='foodproperty',
|
||||
constraint=models.UniqueConstraint(fields=('food', 'property_type', 'space'), name='food_property_unique_per_space'),
|
||||
),
|
||||
]
|
@ -1,73 +0,0 @@
|
||||
# Generated by Django 4.1.7 on 2023-03-25 05:48
|
||||
|
||||
import cookbook.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django_prometheus.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cookbook', '0188_space_no_sharing_limit'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='unit',
|
||||
name='base_unit',
|
||||
field=models.TextField(blank=True, default=None, max_length=256, null=True),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UnitConversion',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('base_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)),
|
||||
('converted_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('base_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_base_relation', to='cookbook.unit')),
|
||||
('converted_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_converted_relation', to='cookbook.unit')),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||
('food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')),
|
||||
('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')),
|
||||
],
|
||||
bases=(django_prometheus.models.ExportModelOperationsMixin('unit_conversion'), models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FoodPropertyType',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('unit', models.CharField(blank=True, max_length=64, null=True)),
|
||||
('icon', models.CharField(blank=True, max_length=16, null=True)),
|
||||
('description', models.CharField(blank=True, max_length=512, null=True)),
|
||||
('category', models.CharField(choices=[('NUTRITION', 'Nutrition'), ('ALLERGEN', 'Allergen'), ('PRICE', 'PRICE')], max_length=64)),
|
||||
('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FoodProperty',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('food_amount', models.DecimalField(decimal_places=2, default=0, max_digits=32)),
|
||||
('nutrition_amount', models.DecimalField(decimal_places=4, default=0, max_digits=32)),
|
||||
('food', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')),
|
||||
('food_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.unit')),
|
||||
('nutrition_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.foodpropertytype')),
|
||||
('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='foodpropertytype',
|
||||
constraint=models.UniqueConstraint(fields=('space', 'name'), name='nutrition_type_unique_name_per_space'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='foodproperty',
|
||||
constraint=models.UniqueConstraint(fields=('food', 'nutrition_type', 'space'), name='food_nutrition_unique_per_space'),
|
||||
),
|
||||
]
|
@ -1,44 +0,0 @@
|
||||
# Generated by Django 4.1.7 on 2023-03-25 06:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0189_unit_base_unit_unitconversion_foodpropertytype_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveConstraint(
|
||||
model_name='foodproperty',
|
||||
name='food_nutrition_unique_per_space',
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name='foodpropertytype',
|
||||
name='nutrition_type_unique_name_per_space',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='foodproperty',
|
||||
old_name='nutrition_amount',
|
||||
new_name='property_amount',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='foodproperty',
|
||||
old_name='nutrition_type',
|
||||
new_name='property_type',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='foodpropertytype',
|
||||
name='category',
|
||||
field=models.CharField(blank=True, choices=[('NUTRITION', 'Nutrition'), ('ALLERGEN', 'Allergen'), ('PRICE', 'PRICE')], max_length=64, null=True),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='foodproperty',
|
||||
constraint=models.UniqueConstraint(fields=('food', 'property_type', 'space'), name='food_property_unique_per_space'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='foodpropertytype',
|
||||
constraint=models.UniqueConstraint(fields=('space', 'name'), name='food_property_type_unique_name_per_space'),
|
||||
),
|
||||
]
|
@ -1,64 +0,0 @@
|
||||
# Generated by Django 4.1.7 on 2023-04-30 20:11
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0190_remove_foodproperty_food_nutrition_unique_per_space_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='foodpropertytype',
|
||||
name='fdc_id',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='foodpropertytype',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='foodpropertytype',
|
||||
name='preferred_shopping_unit',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_shopping_unit', to='cookbook.unit'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='foodpropertytype',
|
||||
name='preferred_unit',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_unit', to='cookbook.unit'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='supermarket',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='supermarketcategory',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unit',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unitconversion',
|
||||
name='open_data_slug',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='foodpropertytype',
|
||||
name='category',
|
||||
field=models.CharField(blank=True, choices=[('NUTRITION', 'Nutrition'), ('ALLERGEN', 'Allergen'), ('PRICE', 'Price'), ('GOAL', 'Goal'), ('OTHER', 'Other')], max_length=64, null=True),
|
||||
),
|
||||
]
|
@ -1,41 +0,0 @@
|
||||
# Generated by Django 4.1.7 on 2023-05-01 10:41
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0191_food_open_data_slug_foodpropertytype_fdc_id_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='foodpropertytype',
|
||||
name='fdc_id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='foodpropertytype',
|
||||
name='preferred_shopping_unit',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='foodpropertytype',
|
||||
name='preferred_unit',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='fdc_id',
|
||||
field=models.CharField(blank=True, default=None, max_length=128, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='preferred_shopping_unit',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_shopping_unit', to='cookbook.unit'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='preferred_unit',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_unit', to='cookbook.unit'),
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 4.1.7 on 2023-05-04 05:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0192_remove_foodpropertytype_fdc_id_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddConstraint(
|
||||
model_name='unitconversion',
|
||||
constraint=models.UniqueConstraint(fields=('space', 'base_unit', 'converted_unit', 'food'), name='f_unique_conversion_per_space'),
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 4.1.7 on 2023-05-04 13:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0193_unitconversion_f_unique_conversion_per_space'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddConstraint(
|
||||
model_name='supermarketcategoryrelation',
|
||||
constraint=models.UniqueConstraint(fields=('supermarket', 'category'), name='unique_sm_category_relation'),
|
||||
),
|
||||
]
|
@ -1,34 +0,0 @@
|
||||
# Generated by Django 4.1.7 on 2023-05-06 16:33
|
||||
|
||||
import cookbook.models
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0194_supermarketcategoryrelation_unique_sm_category_relation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name='FoodPropertyType',
|
||||
new_name='PropertyType',
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='RecipeProperty',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('property_amount', models.DecimalField(decimal_places=4, default=0, max_digits=32)),
|
||||
('property_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.propertytype')),
|
||||
('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='recipe',
|
||||
name='properties',
|
||||
field=models.ManyToManyField(blank=True, to='cookbook.recipeproperty'),
|
||||
),
|
||||
]
|
@ -7,6 +7,13 @@ from cookbook.helper.unit_conversion_helper import UnitConversionHelper
|
||||
from cookbook.models import Unit, Food, Ingredient, UnitConversion
|
||||
|
||||
|
||||
def test_base_converter(space_1):
|
||||
uch = UnitConversionHelper(space_1)
|
||||
assert uch.convert_from_to('g', 'kg', 1234) == 1.234
|
||||
assert uch.convert_from_to('kg', 'pound', 2) == 4.40924
|
||||
# TODO add some more tests and test exception
|
||||
|
||||
|
||||
def test_unit_conversions(space_1, space_2, u1_s1):
|
||||
with scopes_disabled():
|
||||
uch = UnitConversionHelper(space_1)
|
||||
@ -159,4 +166,3 @@ def test_unit_conversions(space_1, space_2, u1_s1):
|
||||
assert next(x for x in conversions if x.unit == unit_kg_space_2) is not None
|
||||
assert next(x for x in conversions if x.unit == unit_kg_space_2).amount == 0.1
|
||||
print(conversions)
|
||||
|
||||
|
@ -821,6 +821,8 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
'steps__ingredients__step_set',
|
||||
'steps__ingredients__step_set__recipe_set',
|
||||
'steps__ingredients__food',
|
||||
'steps__ingredients__food__foodproperty_set',
|
||||
'steps__ingredients__food__foodproperty_set__property_type',
|
||||
'steps__ingredients__food__inherit_fields',
|
||||
'steps__ingredients__food__supermarket_category',
|
||||
'steps__ingredients__food__onhand_users',
|
||||
@ -832,7 +834,8 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
'steps__ingredients__unit__unit_conversion_base_relation__base_unit',
|
||||
'steps__ingredients__unit__unit_conversion_converted_relation',
|
||||
'steps__ingredients__unit__unit_conversion_converted_relation__converted_unit',
|
||||
'cooklog_set').select_related('nutrition')
|
||||
'cooklog_set',
|
||||
).select_related('nutrition')
|
||||
|
||||
return super().get_queryset()
|
||||
|
||||
|
@ -46,4 +46,3 @@ pytest-factoryboy==2.5.1
|
||||
pyppeteer==1.0.2
|
||||
validators==0.20.0
|
||||
pytube==12.1.0
|
||||
pint==0.20.1
|
||||
|
Reference in New Issue
Block a user