diff --git a/Dockerfile b/Dockerfile
index 4c6c4bc9..cbf07b59 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,7 +9,7 @@ WORKDIR /opt/recipes
COPY . ./
RUN chmod +x boot.sh
-RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libressl-dev libffi-dev && \
+RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libressl-dev libffi-dev openssl-dev && \
python -m venv venv && \
venv/bin/pip install -r requirements.txt --no-cache-dir &&\
apk --purge del .build-deps
diff --git a/cookbook/forms.py b/cookbook/forms.py
index 17d92865..cc8c45fa 100644
--- a/cookbook/forms.py
+++ b/cookbook/forms.py
@@ -131,39 +131,17 @@ class ShoppingForm(forms.Form):
)
-class ExportForm(forms.Form):
- recipe = forms.ModelChoiceField(
- queryset=Recipe.objects.filter(internal=True).all(),
- widget=SelectWidget
- )
- image = forms.BooleanField(
- help_text=_('Export Base64 encoded image?'),
- required=False
- )
- download = forms.BooleanField(
- help_text=_('Download export directly or show on page?'),
- required=False
- )
-
-
-class ImportForm(forms.Form):
- recipe = forms.CharField(
- widget=forms.Textarea,
- help_text=_('Simply paste a JSON export into this textarea and click import.') # noqa: E501
- )
-
-
class ImportExportBase(forms.Form):
DEFAULT = 'Default'
type = forms.ChoiceField(choices=((DEFAULT, _('Default')),))
-class NewImportForm(ImportExportBase):
+class ImportForm(ImportExportBase):
files = forms.FileField(required=True, widget=forms.ClearableFileInput(attrs={'multiple': True}))
-class NewExportForm(ImportExportBase):
+class ExportForm(ImportExportBase):
recipes = forms.ModelMultipleChoiceField(queryset=Recipe.objects.filter(internal=True).all(), widget=MultiSelectWidget)
diff --git a/cookbook/helper/dal.py b/cookbook/helper/dal.py
index 03d8ed3c..6a109a6d 100644
--- a/cookbook/helper/dal.py
+++ b/cookbook/helper/dal.py
@@ -13,7 +13,7 @@ class BaseAutocomplete(autocomplete.Select2QuerySetView):
qs = self.model.objects.all()
if self.q:
- qs = qs.filter(name__istartswith=self.q)
+ qs = qs.filter(name__icontains=self.q)
return qs
diff --git a/cookbook/templates/export.html b/cookbook/templates/export.html
index cac74ae3..4133da93 100644
--- a/cookbook/templates/export.html
+++ b/cookbook/templates/export.html
@@ -1,6 +1,6 @@
{% extends "base.html" %}
-{% load i18n %}
{% load crispy_forms_filters %}
+{% load i18n %}
{% load static %}
{% block title %}{% trans 'Export Recipes' %}{% endblock %}
@@ -9,8 +9,9 @@
{{ form.media }}
{% endblock %}
-{% block content %}
+{% block content %}
+
{% trans 'Export' %}
-
- {% if export %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% endif %}
{% endblock %}
\ No newline at end of file
diff --git a/cookbook/templates/import.html b/cookbook/templates/import.html
index 96a7be70..d36a8adc 100644
--- a/cookbook/templates/import.html
+++ b/cookbook/templates/import.html
@@ -1,14 +1,20 @@
{% extends "base.html" %}
+{% load crispy_forms_filters %}
{% load i18n %}
-{% load crispy_forms_tags %}
{% load static %}
{% block title %}{% trans 'Import Recipes' %}{% endblock %}
+{% block extra_head %}
+ {{ form.media }}
+{% endblock %}
+
+
{% block content %}
+ {% trans 'Import' %}
+
{% endblock %}
\ No newline at end of file
diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py
index 2d61e03b..e99d4af7 100644
--- a/cookbook/views/import_export.py
+++ b/cookbook/views/import_export.py
@@ -1,76 +1,24 @@
-import base64
-import json
import re
-from json import JSONDecodeError
-from django.contrib import messages
-from django.core.files.base import ContentFile
-from django.http import HttpResponse, HttpResponseRedirect
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.forms import ExportForm, ExportForm, ImportForm
from cookbook.helper.permission_helper import group_required
+from cookbook.integration.default import Default
from cookbook.models import Recipe
-from cookbook.serializer import RecipeSerializer, RecipeExportSerializer
+
+
+def get_integration(request, export_type):
+ return Default(request)
@group_required('user')
def import_recipe(request):
if request.method == "POST":
- form = ImportForm(request.POST)
+ form = ImportForm(request.POST, request.FILES)
if form.is_valid():
- try:
- data = json.loads(
- re.sub(r'"id":([0-9]+),', '', re.sub(r',(\s)*"recipe":([0-9]+)', '', form.cleaned_data['recipe']))
- )
-
- sr = RecipeExportSerializer(data=data, context={'request': request})
- if sr.is_valid():
- sr.validated_data['created_by'] = request.user
- recipe = sr.save()
-
- if data['image']:
- try:
- fmt, img = data['image'].split(';base64,')
- ext = fmt.split('/')[-1]
- # TODO possible security risk,
- # maybe some checks needed
- recipe.image = (ContentFile(
- base64.b64decode(img),
- name=f'{recipe.pk}.{ext}')
- )
- recipe.save()
- except ValueError:
- pass
-
- 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 as e:
- print(e)
- messages.add_message(
- request,
- messages.ERROR,
- _('Could not parse the supplied JSON!')
- )
-
+ integration = Default(request)
+ return integration.do_import(request.FILES.getlist('files'))
else:
form = ImportForm()
@@ -79,41 +27,17 @@ def import_recipe(request):
@group_required('user')
def export_recipe(request):
- context = {}
if request.method == "POST":
form = ExportForm(request.POST)
if form.is_valid():
- recipe = form.cleaned_data['recipe']
- if recipe.internal:
- export = RecipeExportSerializer(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")}' # noqa: E501
-
- json_string = JSONRenderer().render(export).decode("utf-8")
-
- if form.cleaned_data['download']:
- response = HttpResponse(
- json_string, content_type='text/plain'
- )
- response['Content-Disposition'] = f'attachment; filename={recipe.name}.json' # noqa: E501
- return response
-
- 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.') # noqa: E501
- )
+ integration = Default(request)
+ return integration.do_export(form.cleaned_data['recipes'])
else:
form = ExportForm()
recipe = request.GET.get('r')
if recipe:
if re.match(r'^([0-9])+$', recipe):
if recipe := Recipe.objects.filter(pk=int(recipe)).first():
- form = ExportForm(initial={'recipe': recipe})
+ form = ExportForm(initial={'recipes': recipe})
- context['form'] = form
-
- return render(request, 'export.html', context)
+ return render(request, 'export.html', {'form': form})
diff --git a/cookbook/views/views.py b/cookbook/views/views.py
index 69f9efe6..693979d3 100644
--- a/cookbook/views/views.py
+++ b/cookbook/views/views.py
@@ -22,7 +22,7 @@ from rest_framework.authtoken.models import Token
from cookbook.filters import RecipeFilter
from cookbook.forms import (CommentForm, Recipe, RecipeBookEntryForm, User,
UserCreateForm, UserNameForm, UserPreference,
- UserPreferenceForm, ImportForm, NewImportForm, NewExportForm)
+ UserPreferenceForm, ImportForm, ImportForm, ExportForm)
from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission
from cookbook.integration.default import Default
from cookbook.models import (Comment, CookLog, InviteLink, MealPlan,
@@ -490,27 +490,7 @@ def test(request):
if not settings.DEBUG:
return HttpResponseRedirect(reverse('index'))
- if request.method == "POST":
- form = NewImportForm(request.POST, request.FILES)
- if form.is_valid():
- integration = Default(request)
- return integration.do_import(request.FILES.getlist('files'))
- else:
- form = NewImportForm()
-
- return render(request, 'test.html', {'form': form})
-
def test2(request):
if not settings.DEBUG:
return HttpResponseRedirect(reverse('index'))
-
- if request.method == "POST":
- form = NewExportForm(request.POST)
- if form.is_valid():
- integration = Default(request)
- return integration.do_export(form.cleaned_data['recipes'])
- else:
- form = NewExportForm()
-
- return render(request, 'test2.html', {'form': form})