From 19f5da77b2803f5002a13af9730cf9383c9a70f8 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sat, 6 May 2023 22:21:27 +0200 Subject: [PATCH] cleanup migrations, remove pint to speed up base conversion and calculate properties on converted ingredients --- cookbook/helper/open_data_importer.py | 3 +- cookbook/helper/property_helper.py | 2 +- cookbook/helper/unit_conversion_helper.py | 81 +++++--- ...ty_propertytype_recipeproperty_and_more.py | 181 ++++++++++++++++++ ...nitconversion_foodpropertytype_and_more.py | 73 ------- ...ood_nutrition_unique_per_space_and_more.py | 44 ----- ...a_slug_foodpropertytype_fdc_id_and_more.py | 64 ------- ...remove_foodpropertytype_fdc_id_and_more.py | 41 ---- ...onversion_f_unique_conversion_per_space.py | 17 -- ...oryrelation_unique_sm_category_relation.py | 17 -- ...pe_propertytype_recipeproperty_and_more.py | 34 ---- cookbook/tests/other/test_unit_conversion.py | 8 +- cookbook/views/api.py | 5 +- requirements.txt | 1 - 14 files changed, 249 insertions(+), 322 deletions(-) create mode 100644 cookbook/migrations/0189_foodproperty_propertytype_recipeproperty_and_more.py delete mode 100644 cookbook/migrations/0189_unit_base_unit_unitconversion_foodpropertytype_and_more.py delete mode 100644 cookbook/migrations/0190_remove_foodproperty_food_nutrition_unique_per_space_and_more.py delete mode 100644 cookbook/migrations/0191_food_open_data_slug_foodpropertytype_fdc_id_and_more.py delete mode 100644 cookbook/migrations/0192_remove_foodpropertytype_fdc_id_and_more.py delete mode 100644 cookbook/migrations/0193_unitconversion_f_unique_conversion_per_space.py delete mode 100644 cookbook/migrations/0194_supermarketcategoryrelation_unique_sm_category_relation.py delete mode 100644 cookbook/migrations/0195_rename_foodpropertytype_propertytype_recipeproperty_and_more.py diff --git a/cookbook/helper/open_data_importer.py b/cookbook/helper/open_data_importer.py index 0bd3ac51d..a8f6cfa53 100644 --- a/cookbook/helper/open_data_importer.py +++ b/cookbook/helper/open_data_importer.py @@ -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') diff --git a/cookbook/helper/property_helper.py b/cookbook/helper/property_helper.py index 3007a7e3d..ef154fd8f 100644 --- a/cookbook/helper/property_helper.py +++ b/cookbook/helper/property_helper.py @@ -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(): diff --git a/cookbook/helper/unit_conversion_helper.py b/cookbook/helper/unit_conversion_helper.py index bc3ad24b3..033c48250 100644 --- a/cookbook/helper/unit_conversion_helper.py +++ b/cookbook/helper/unit_conversion_helper.py @@ -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 - # }, - # } diff --git a/cookbook/migrations/0189_foodproperty_propertytype_recipeproperty_and_more.py b/cookbook/migrations/0189_foodproperty_propertytype_recipeproperty_and_more.py new file mode 100644 index 000000000..4cf22a46d --- /dev/null +++ b/cookbook/migrations/0189_foodproperty_propertytype_recipeproperty_and_more.py @@ -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'), + ), + ] diff --git a/cookbook/migrations/0189_unit_base_unit_unitconversion_foodpropertytype_and_more.py b/cookbook/migrations/0189_unit_base_unit_unitconversion_foodpropertytype_and_more.py deleted file mode 100644 index b2b0467cb..000000000 --- a/cookbook/migrations/0189_unit_base_unit_unitconversion_foodpropertytype_and_more.py +++ /dev/null @@ -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'), - ), - ] diff --git a/cookbook/migrations/0190_remove_foodproperty_food_nutrition_unique_per_space_and_more.py b/cookbook/migrations/0190_remove_foodproperty_food_nutrition_unique_per_space_and_more.py deleted file mode 100644 index 58d784687..000000000 --- a/cookbook/migrations/0190_remove_foodproperty_food_nutrition_unique_per_space_and_more.py +++ /dev/null @@ -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'), - ), - ] diff --git a/cookbook/migrations/0191_food_open_data_slug_foodpropertytype_fdc_id_and_more.py b/cookbook/migrations/0191_food_open_data_slug_foodpropertytype_fdc_id_and_more.py deleted file mode 100644 index cf16c8ba2..000000000 --- a/cookbook/migrations/0191_food_open_data_slug_foodpropertytype_fdc_id_and_more.py +++ /dev/null @@ -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), - ), - ] diff --git a/cookbook/migrations/0192_remove_foodpropertytype_fdc_id_and_more.py b/cookbook/migrations/0192_remove_foodpropertytype_fdc_id_and_more.py deleted file mode 100644 index a64f1f6cb..000000000 --- a/cookbook/migrations/0192_remove_foodpropertytype_fdc_id_and_more.py +++ /dev/null @@ -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'), - ), - ] diff --git a/cookbook/migrations/0193_unitconversion_f_unique_conversion_per_space.py b/cookbook/migrations/0193_unitconversion_f_unique_conversion_per_space.py deleted file mode 100644 index 9c964285a..000000000 --- a/cookbook/migrations/0193_unitconversion_f_unique_conversion_per_space.py +++ /dev/null @@ -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'), - ), - ] diff --git a/cookbook/migrations/0194_supermarketcategoryrelation_unique_sm_category_relation.py b/cookbook/migrations/0194_supermarketcategoryrelation_unique_sm_category_relation.py deleted file mode 100644 index a153d6d15..000000000 --- a/cookbook/migrations/0194_supermarketcategoryrelation_unique_sm_category_relation.py +++ /dev/null @@ -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'), - ), - ] diff --git a/cookbook/migrations/0195_rename_foodpropertytype_propertytype_recipeproperty_and_more.py b/cookbook/migrations/0195_rename_foodpropertytype_propertytype_recipeproperty_and_more.py deleted file mode 100644 index 150accadc..000000000 --- a/cookbook/migrations/0195_rename_foodpropertytype_propertytype_recipeproperty_and_more.py +++ /dev/null @@ -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'), - ), - ] diff --git a/cookbook/tests/other/test_unit_conversion.py b/cookbook/tests/other/test_unit_conversion.py index adc9d15cc..a2e163d86 100644 --- a/cookbook/tests/other/test_unit_conversion.py +++ b/cookbook/tests/other/test_unit_conversion.py @@ -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) - diff --git a/cookbook/views/api.py b/cookbook/views/api.py index a73e96da4..a77ea5ca6 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -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() diff --git a/requirements.txt b/requirements.txt index 5f45e930c..b96fc67f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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