diff --git a/cookbook/serializer.py b/cookbook/serializer.py
index b50469205..862a24d88 100644
--- a/cookbook/serializer.py
+++ b/cookbook/serializer.py
@@ -1,4 +1,5 @@
from django.contrib.auth.models import User
+from drf_writable_nested import WritableNestedModelSerializer, UniqueFieldsMixin
from rest_framework import serializers
from rest_framework.exceptions import APIException
from rest_framework.fields import CurrentUserDefault
@@ -38,71 +39,50 @@ class SyncLogSerializer(serializers.ModelSerializer):
fields = '__all__'
-class KeywordSerializer(serializers.ModelSerializer):
+class KeywordSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
class Meta:
model = Keyword
fields = '__all__'
- validators = []
- extra_kwargs = {
- "name": {
- "validators": [],
- },
- }
-
- def validate(self, attrs):
- return attrs
-class UnitSerializer(serializers.ModelSerializer):
+class UnitSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
class Meta:
model = Unit
fields = '__all__'
-class FoodSerializer(serializers.ModelSerializer):
+class FoodSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
class Meta:
model = Food
fields = '__all__'
-class IngredientSerializer(serializers.ModelSerializer):
- food = FoodSerializer(read_only=True)
- unit = UnitSerializer(read_only=True)
+class IngredientSerializer(WritableNestedModelSerializer):
+ food = FoodSerializer()
+ unit = UnitSerializer()
class Meta:
model = Ingredient
fields = '__all__'
-class StepSerializer(serializers.ModelSerializer):
- ingredients = IngredientSerializer(many=True, read_only=True)
+class StepSerializer(WritableNestedModelSerializer):
+ ingredients = IngredientSerializer(many=True)
class Meta:
model = Step
fields = '__all__'
-class RecipeSerializer(serializers.ModelSerializer):
- steps = StepSerializer(many=True, read_only=True)
- keywords = KeywordSerializer(many=True, read_only=False, validators=[])
+class RecipeSerializer(WritableNestedModelSerializer):
+ steps = StepSerializer(many=True)
+ keywords = KeywordSerializer(many=True)
class Meta:
model = Recipe
fields = '__all__'
validators = []
- def update(self, instance, validated_data):
- for k in validated_data['keyword']:
- pass
- return instance
-
- def create(self, validated_data):
- print('test')
- pass
-
- def validate(self, attrs):
- return attrs
-
class RecipeImportSerializer(serializers.ModelSerializer):
class Meta:
diff --git a/cookbook/templates/forms/edit_internal_recipe.html b/cookbook/templates/forms/edit_internal_recipe.html
index 82c1ecb99..7f0397e9d 100644
--- a/cookbook/templates/forms/edit_internal_recipe.html
+++ b/cookbook/templates/forms/edit_internal_recipe.html
@@ -61,7 +61,82 @@
-
+
+
+
+
Step [[index + 1]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -81,6 +156,10 @@
recipe: undefined,
keywords: [],
keywords_loading: false,
+ foods: [],
+ foods_loading: false,
+ units: [],
+ units_loading: false,
},
directives: {
tabindex: {
@@ -91,6 +170,9 @@
},
mounted: function () {
this.loadRecipe()
+ this.searchUnits('')
+ this.searchFoods('')
+ this.searchKeywords('')
},
methods: {
loadRecipe: function () {
@@ -110,15 +192,41 @@
console.log(err)
})
},
+ addStep: function () { //TODO see if default can be generated from options request
+ this.recipe.steps.push(
+ {'instruction': '', ingredients: []}
+ )
+ },
searchKeywords: function (query) {
this.keywords_loading = true
- this.$http.get("{% url 'api:keyword-list' %}" + '?query=' + query).then((response) => {
+ this.$http.get("{% url 'api:keyword-list' %}" + '?query=' + query + '&limit=10').then((response) => {
this.keywords = response.data;
this.keywords_loading = false
}).catch((err) => {
console.log(err)
})
},
+ searchUnits: function (query) {
+ this.units_loading = true
+ this.$http.get("{% url 'api:unit-list' %}" + '?query=' + query + '&limit=10').then((response) => {
+ this.units = response.data;
+ //TODO add back code to include custom created ingredients
+ this.units_loading = false
+ }).catch((err) => {
+ console.log(err)
+ })
+ },
+ searchFoods: function (query) {
+ this.foods_loading = true
+ this.$http.get("{% url 'api:food-list' %}" + '?query=' + query + '&limit=10').then((response) => {
+ this.foods = response.data
+ //TODO add back code to include custom created ingredients
+
+ this.foods_loading = false
+ }).catch((err) => {
+ console.log(err)
+ })
+ },
}
});
diff --git a/cookbook/views/api.py b/cookbook/views/api.py
index 6962dea51..2850ffbad 100644
--- a/cookbook/views/api.py
+++ b/cookbook/views/api.py
@@ -18,7 +18,7 @@ from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, ListMode
from cookbook.helper.permission_helper import group_required, CustomIsOwner, CustomIsAdmin, CustomIsUser
from cookbook.helper.recipe_url_import import get_from_html
-from cookbook.models import Recipe, Sync, Storage, CookLog, MealPlan, MealType, ViewLog, UserPreference, RecipeBook, Ingredient, Food, Step, Keyword
+from cookbook.models import Recipe, Sync, Storage, CookLog, MealPlan, MealType, ViewLog, UserPreference, RecipeBook, Ingredient, Food, Step, Keyword, Unit
from cookbook.provider.dropbox import Dropbox
from cookbook.provider.nextcloud import Nextcloud
from cookbook.serializer import MealPlanSerializer, MealTypeSerializer, RecipeSerializer, ViewLogSerializer, UserNameSerializer, UserPreferenceSerializer, RecipeBookSerializer, IngredientSerializer, FoodSerializer, StepSerializer, \
@@ -112,16 +112,38 @@ class MealTypeViewSet(viewsets.ModelViewSet):
class UnitViewSet(viewsets.ModelViewSet):
- queryset = Food.objects.all()
+ queryset = Unit.objects.all()
serializer_class = FoodSerializer
permission_classes = [CustomIsUser]
+ def get_queryset(self): # TODO create standard filter/limit mixin
+ queryset = self.queryset
+ query = self.request.query_params.get('query', None)
+ if query is not None:
+ queryset = queryset.filter(name__icontains=query)
+
+ limit = self.request.query_params.get('limit', None)
+ if limit is not None:
+ queryset = queryset[:int(limit)]
+ return queryset
+
class FoodViewSet(viewsets.ModelViewSet):
queryset = Food.objects.all()
serializer_class = FoodSerializer
permission_classes = [CustomIsUser]
+ def get_queryset(self): # TODO create standard filter/limit mixin
+ queryset = self.queryset
+ query = self.request.query_params.get('query', None)
+ if query is not None:
+ queryset = queryset.filter(name__icontains=query)
+
+ limit = self.request.query_params.get('limit', None)
+ if limit is not None:
+ queryset = queryset[:int(limit)]
+ return queryset
+
class IngredientViewSet(viewsets.ModelViewSet):
queryset = Ingredient.objects.all()
@@ -147,7 +169,7 @@ class RecipeViewSet(viewsets.ModelViewSet):
serializer_class = RecipeSerializer
permission_classes = [permissions.IsAuthenticated] # TODO split read and write permission for meal plan guest
- def get_queryset(self):
+ def get_queryset(self): # TODO create standard filter/limit mixin
queryset = Recipe.objects.all()
query = self.request.query_params.get('query', None)
if query is not None:
@@ -171,7 +193,7 @@ class KeywordViewSet(viewsets.ModelViewSet):
serializer_class = KeywordSerializer
permission_classes = [CustomIsUser]
- def get_queryset(self):
+ def get_queryset(self): # TODO create standard filter/limit mixin
queryset = Keyword.objects.all()
query = self.request.query_params.get('query', None)
if query is not None:
diff --git a/requirements.txt b/requirements.txt
index 7006b3cb5..156a34765 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,6 +9,7 @@ django-emoji-picker==0.0.6
django-filter==2.2.0
django-tables2==2.3.1
djangorestframework==3.11.0
+drf-writable-nested==0.6.0
gunicorn==20.0.4
lxml==4.5.1
Markdown==3.2.2