fixed import export

This commit is contained in:
vabene1111 2020-06-29 19:09:15 +02:00
parent 38e5882376
commit 577af85d38
3 changed files with 54 additions and 70 deletions

View File

@ -42,7 +42,7 @@ class UserPreferenceSerializer(serializers.ModelSerializer):
class StorageSerializer(serializers.ModelSerializer):
class Meta:
model = Storage
fields = ('name', 'method', 'username', 'created_by')
fields = ('id', 'name', 'method', 'username', 'created_by')
class SyncSerializer(serializers.ModelSerializer):
@ -58,9 +58,16 @@ class SyncLogSerializer(serializers.ModelSerializer):
class KeywordSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
def create(self, validated_data):
# since multi select tags dont have id's duplicate names might be routed to create
obj, created = Keyword.objects.get_or_create(**validated_data)
return obj
class Meta:
model = Keyword
fields = '__all__'
fields = ('id', 'name', 'icon', 'description', 'created_by', 'created_at', 'updated_at')
read_only_fields = ('id',)
class UnitSerializer(UniqueFieldsMixin, serializers.ModelSerializer):

View File

@ -314,7 +314,9 @@
addIngredient: function (step) { //TODO see if default can be generated from options request
step.ingredients.push({
'food': undefined,
'unit': undefined,
'unit': {
'name': '{{request.user.userpreference.default_unit}}'
},
'amount': 0,
'note': '',
'order': 0,
@ -355,10 +357,13 @@
this.units_loading = true
this.$http.get("{% url 'api:unit-list' %}" + '?query=' + query + '&limit=10').then((response) => {
this.units = response.data;
for (let s of this.recipe.steps){
for (let i of s.ingredients) {
if (i.unit.id === undefined) {
this.units.push(i.unit)
if (this.recipe !== undefined) {
for (let s of this.recipe.steps) {
for (let i of s.ingredients) {
if (i.unit.id === undefined) {
this.units.push(i.unit)
}
}
}
}
@ -372,10 +377,12 @@
this.$http.get("{% url 'api:food-list' %}" + '?query=' + query + '&limit=10').then((response) => {
this.foods = response.data
for (let s of this.recipe.steps){
for (let i of s.ingredients) {
if (i.food.id === undefined) {
this.foods.push(i.food)
if (this.recipe !== undefined) {
for (let s of this.recipe.steps) {
for (let i of s.ingredients) {
if (i.food.id === undefined) {
this.foods.push(i.food)
}
}
}
}

View File

@ -1,18 +1,20 @@
import base64
import json
import re
from json import JSONDecodeError
from django.contrib import messages
from django.core.files.base import ContentFile
from django.db import IntegrityError
from django.http import HttpResponseRedirect, JsonResponse, HttpResponse
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from rest_framework.renderers import JSONRenderer
from cookbook.forms import ExportForm, ImportForm
from cookbook.helper.permission_helper import group_required
from cookbook.models import Ingredient, Recipe, Unit, Food, Keyword, Food
from cookbook.models import Recipe
from cookbook.serializer import RecipeSerializer
@group_required('user')
@ -20,44 +22,28 @@ def import_recipe(request):
if request.method == "POST":
form = ImportForm(request.POST)
if form.is_valid():
data = json.loads(form.cleaned_data['recipe'])
try:
data = json.loads(form.cleaned_data['recipe'])
recipe = Recipe.objects.create(name=data['recipe']['name'], instructions=data['recipe']['instructions'],
working_time=data['recipe']['working_time'], waiting_time=data['recipe']['waiting_time'],
created_by=request.user, internal=True)
sr = RecipeSerializer(data=data)
if sr.is_valid():
sr.validated_data['created_by'] = request.user
recipe = sr.save()
for k in data['keywords']:
try:
Keyword.objects.create(name=k['name'], icon=k['icon'], description=k['description']).save()
except IntegrityError:
pass
if data['image']:
fmt, img = data['image'].split(';base64,')
ext = fmt.split('/')[-1]
recipe.image = ContentFile(base64.b64decode(img), name=f'{recipe.pk}.{ext}') # TODO possible security risk, maybe some checks needed
recipe.save()
recipe.keywords.add(Keyword.objects.get(name=k['name']))
messages.add_message(request, messages.SUCCESS, _('Recipe imported successfully!'))
return HttpResponseRedirect(reverse_lazy('view_recipe', args=[recipe.pk]))
else:
messages.add_message(request, messages.ERROR, _('Something went wrong during the import!'))
messages.add_message(request, messages.WARNING, sr.errors)
except JSONDecodeError:
messages.add_message(request, messages.ERROR, _('Could not parse the supplied JSON!'))
for u in data['units']:
try:
Unit.objects.create(name=u['name'], description=u['description']).save()
except IntegrityError:
pass
for i in data['ingredients']:
try:
Food.objects.create(name=i['name']).save()
except IntegrityError:
pass
for ri in data['recipe_ingredients']:
Ingredient.objects.create(recipe=recipe, ingredient=Food.objects.get(name=ri['food']),
unit=Unit.objects.get(name=ri['unit']), amount=ri['amount'], note=ri['note'])
if data['image']:
fmt, img = data['image'].split(';base64,')
ext = fmt.split('/')[-1]
recipe.image = ContentFile(base64.b64decode(img), name=f'{recipe.pk}.{ext}')
recipe.save()
messages.add_message(request, messages.SUCCESS, _('Recipe imported successfully!'))
return HttpResponseRedirect(reverse_lazy('view_recipe', args=[recipe.pk]))
else:
form = ImportForm()
@ -72,36 +58,20 @@ def export_recipe(request):
if form.is_valid():
recipe = form.cleaned_data['recipe']
if recipe.internal:
export = {
'recipe': {'name': recipe.name, 'instructions': recipe.instructions, 'working_time': recipe.working_time, 'waiting_time': recipe.working_time},
'units': [],
'ingredients': [],
'recipe_ingredients': [],
'keywords': [],
'image': None
}
for k in recipe.keywords.all():
export['keywords'].append({'name': k.name, 'icon': k.icon, 'description': k.description})
for ri in Ingredient.objects.filter(recipe=recipe).all():
if ri.unit not in export['units']:
export['units'].append({'name': ri.unit.name, 'description': ri.unit.description})
if ri.ingredient not in export['ingredients']:
export['ingredients'].append({'name': ri.ingredient.name})
export['recipe_ingredients'].append({'food': ri.ingredient.name, 'unit': ri.unit.name, 'amount': float(ri.amount), 'note': ri.note})
export = RecipeSerializer(recipe).data
if recipe.image and form.cleaned_data['image']:
with open(recipe.image.path, 'rb') as img_f:
export['image'] = f'data:image/png;base64,{base64.b64encode(img_f.read()).decode("utf-8")}'
json_string = JSONRenderer().render(export).decode("utf-8")
if form.cleaned_data['download']:
response = HttpResponse(json.dumps(export), content_type='text/plain')
response = HttpResponse(json_string, content_type='text/plain')
response['Content-Disposition'] = f'attachment; filename={recipe.name}.json'
return response
context['export'] = json.dumps(export, indent=4)
context['export'] = re.sub(r'"id":([0-9])+,', '', json_string)
else:
form.add_error('recipe', _('External recipes cannot be exported, please share the file directly or select an internal recipe.'))
else: