moved import functions to proper api function
This commit is contained in:
parent
c50efac00e
commit
ac2ab62050
@ -1,26 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load crispy_forms_filters %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block title %}{% trans 'Import Recipes' %}{% endblock %}
|
|
||||||
|
|
||||||
{% block extra_head %}
|
|
||||||
{{ form.media }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h2>{% trans 'Import' %}</h2>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
<form action="." method="post" enctype="multipart/form-data">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form|crispy }}
|
|
||||||
<button class="btn btn-success" type="submit"><i class="fas fa-file-import"></i> {% trans 'Import' %}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -1,18 +0,0 @@
|
|||||||
<!--
|
|
||||||
As there is apparently no good way to pass django named URLs to Vue/Webpack we will pack the urls we need into
|
|
||||||
this object and load it in all the templates where we load Vue apps
|
|
||||||
|
|
||||||
Reason for not using other alternatives
|
|
||||||
|
|
||||||
## django-js-reverse
|
|
||||||
bad performance because the 25kb or so path file needs to be loaded before any other request can be made
|
|
||||||
or all paths need to be printed in template which is apparently not recommended for CSP reasons (although this here
|
|
||||||
might do the same)
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<script type="application/javascript">
|
|
||||||
window.DJANGO_URLS = {
|
|
||||||
'edit_storage'
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -73,7 +73,7 @@ urlpatterns = [
|
|||||||
path('ingredient-editor/', views.ingredient_editor, name='view_ingredient_editor'),
|
path('ingredient-editor/', views.ingredient_editor, name='view_ingredient_editor'),
|
||||||
path('abuse/<slug:token>', views.report_share_abuse, name='view_report_share_abuse'),
|
path('abuse/<slug:token>', views.report_share_abuse, name='view_report_share_abuse'),
|
||||||
|
|
||||||
path('import/', import_export.import_recipe, name='view_import'),
|
path('api/import/', api.import_files, name='view_import'),
|
||||||
path('import-response/<int:pk>/', import_export.import_response, name='view_import_response'),
|
path('import-response/<int:pk>/', import_export.import_response, name='view_import_response'),
|
||||||
path('export/', import_export.export_recipe, name='view_export'),
|
path('export/', import_export.export_recipe, name='view_export'),
|
||||||
path('export-response/<int:pk>/', import_export.export_response, name='view_export_response'),
|
path('export-response/<int:pk>/', import_export.export_response, name='view_export_response'),
|
||||||
|
@ -2,6 +2,7 @@ import io
|
|||||||
import json
|
import json
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import re
|
import re
|
||||||
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
import uuid
|
import uuid
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
@ -44,6 +45,7 @@ from rest_framework.throttling import AnonRateThrottle
|
|||||||
from rest_framework.viewsets import ViewSetMixin
|
from rest_framework.viewsets import ViewSetMixin
|
||||||
from treebeard.exceptions import InvalidMoveToDescendant, InvalidPosition, PathOverflow
|
from treebeard.exceptions import InvalidMoveToDescendant, InvalidPosition, PathOverflow
|
||||||
|
|
||||||
|
from cookbook.forms import ImportForm
|
||||||
from cookbook.helper import recipe_url_import as helper
|
from cookbook.helper import recipe_url_import as helper
|
||||||
from cookbook.helper.HelperFunctions import str2bool
|
from cookbook.helper.HelperFunctions import str2bool
|
||||||
from cookbook.helper.image_processing import handle_image
|
from cookbook.helper.image_processing import handle_image
|
||||||
@ -51,7 +53,7 @@ from cookbook.helper.ingredient_parser import IngredientParser
|
|||||||
from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, CustomIsOwner,
|
from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, CustomIsOwner,
|
||||||
CustomIsOwnerReadOnly, CustomIsShare, CustomIsShared,
|
CustomIsOwnerReadOnly, CustomIsShare, CustomIsShared,
|
||||||
CustomIsSpaceOwner, CustomIsUser, group_required,
|
CustomIsSpaceOwner, CustomIsUser, group_required,
|
||||||
is_space_owner, switch_user_active_space)
|
is_space_owner, switch_user_active_space, above_space_limit)
|
||||||
from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch
|
from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch
|
||||||
from cookbook.helper.recipe_url_import import get_from_youtube_scraper, get_images_from_soup
|
from cookbook.helper.recipe_url_import import get_from_youtube_scraper, get_images_from_soup
|
||||||
from cookbook.helper.scrapers.scrapers import text_scraper
|
from cookbook.helper.scrapers.scrapers import text_scraper
|
||||||
@ -85,6 +87,7 @@ from cookbook.serializer import (AutomationSerializer, BookmarkletImportListSeri
|
|||||||
SyncLogSerializer, SyncSerializer, UnitSerializer,
|
SyncLogSerializer, SyncSerializer, UnitSerializer,
|
||||||
UserFileSerializer, UserNameSerializer, UserPreferenceSerializer,
|
UserFileSerializer, UserNameSerializer, UserPreferenceSerializer,
|
||||||
UserSpaceSerializer, ViewLogSerializer)
|
UserSpaceSerializer, ViewLogSerializer)
|
||||||
|
from cookbook.views.import_export import get_integration
|
||||||
from recipes import settings
|
from recipes import settings
|
||||||
|
|
||||||
|
|
||||||
@ -720,7 +723,7 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
|||||||
'Query string matched (fuzzy) against recipe name. In the future also fulltext search.')),
|
'Query string matched (fuzzy) against recipe name. In the future also fulltext search.')),
|
||||||
QueryParam(name='keywords', description=_(
|
QueryParam(name='keywords', description=_(
|
||||||
'ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or'),
|
'ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or'),
|
||||||
qtype='int'),
|
qtype='int'),
|
||||||
QueryParam(name='keywords_or',
|
QueryParam(name='keywords_or',
|
||||||
description=_('Keyword IDs, repeat for multiple. Return recipes with any of the keywords'),
|
description=_('Keyword IDs, repeat for multiple. Return recipes with any of the keywords'),
|
||||||
qtype='int'),
|
qtype='int'),
|
||||||
@ -1258,6 +1261,35 @@ def download_file(request, file_id):
|
|||||||
return Response({}, status=status.HTTP_400_BAD_REQUEST)
|
return Response({}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
# @schema(AutoSchema()) #TODO add proper schema
|
||||||
|
@permission_classes([CustomIsUser])
|
||||||
|
def import_files(request):
|
||||||
|
"""
|
||||||
|
function to handle files passed by application importer
|
||||||
|
"""
|
||||||
|
limit, msg = above_space_limit(request.space)
|
||||||
|
if limit:
|
||||||
|
return Response({'error': msg}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
form = ImportForm(request.POST, request.FILES)
|
||||||
|
if form.is_valid() and request.FILES != {}:
|
||||||
|
try:
|
||||||
|
integration = get_integration(request, form.cleaned_data['type'])
|
||||||
|
|
||||||
|
il = ImportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space)
|
||||||
|
files = []
|
||||||
|
for f in request.FILES.getlist('files'):
|
||||||
|
files.append({'file': io.BytesIO(f.read()), 'name': f.name})
|
||||||
|
t = threading.Thread(target=integration.do_import, args=[files, il, form.cleaned_data['duplicates']])
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
return Response({'import_id': il.pk}, status=status.HTTP_200_OK)
|
||||||
|
except NotImplementedError:
|
||||||
|
return Response({'error': True, 'msg': _('Importing is not implemented for this provider')}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
def get_recipe_provider(recipe):
|
def get_recipe_provider(recipe):
|
||||||
if recipe.storage.method == Storage.DROPBOX:
|
if recipe.storage.method == Storage.DROPBOX:
|
||||||
return Dropbox
|
return Dropbox
|
||||||
|
@ -82,42 +82,6 @@ def get_integration(request, export_type):
|
|||||||
return Cookmate(request, export_type)
|
return Cookmate(request, export_type)
|
||||||
|
|
||||||
|
|
||||||
@group_required('user')
|
|
||||||
def import_recipe(request):
|
|
||||||
limit, msg = above_space_limit(request.space)
|
|
||||||
if limit:
|
|
||||||
messages.add_message(request, messages.WARNING, msg)
|
|
||||||
return HttpResponseRedirect(reverse('index'))
|
|
||||||
|
|
||||||
if request.method == "POST":
|
|
||||||
form = ImportForm(request.POST, request.FILES)
|
|
||||||
if form.is_valid() and request.FILES != {}:
|
|
||||||
try:
|
|
||||||
integration = get_integration(request, form.cleaned_data['type'])
|
|
||||||
|
|
||||||
il = ImportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space)
|
|
||||||
files = []
|
|
||||||
for f in request.FILES.getlist('files'):
|
|
||||||
files.append({'file': BytesIO(f.read()), 'name': f.name})
|
|
||||||
t = threading.Thread(target=integration.do_import, args=[files, il, form.cleaned_data['duplicates']])
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
|
|
||||||
return JsonResponse({'import_id': il.pk})
|
|
||||||
except NotImplementedError:
|
|
||||||
return JsonResponse(
|
|
||||||
{
|
|
||||||
'error': True,
|
|
||||||
'msg': _('Importing is not implemented for this provider')
|
|
||||||
},
|
|
||||||
status=400
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
form = ImportForm()
|
|
||||||
|
|
||||||
return render(request, 'import.html', {'form': form})
|
|
||||||
|
|
||||||
|
|
||||||
@group_required('user')
|
@group_required('user')
|
||||||
def export_recipe(request):
|
def export_recipe(request):
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
Loading…
Reference in New Issue
Block a user