added paprika import
This commit is contained in:
parent
ec842aa657
commit
79da8db889
@ -132,9 +132,10 @@ class ShoppingForm(forms.Form):
|
||||
|
||||
|
||||
class ImportExportBase(forms.Form):
|
||||
DEFAULT = 'Default'
|
||||
DEFAULT = 'DEFAULT'
|
||||
PAPRIKA = 'PAPRIKA'
|
||||
|
||||
type = forms.ChoiceField(choices=((DEFAULT, _('Default')),))
|
||||
type = forms.ChoiceField(choices=((DEFAULT, _('Default')), (PAPRIKA, _('Paprika')),))
|
||||
|
||||
|
||||
class ImportForm(ImportExportBase):
|
||||
|
@ -31,7 +31,7 @@ def get_from_html(html_text, url):
|
||||
|
||||
if ('@type' in ld_json_item
|
||||
and ld_json_item['@type'] == 'Recipe'):
|
||||
return find_recipe_json(ld_json_item, url)
|
||||
return JsonResponse(find_recipe_json(ld_json_item, url))
|
||||
except JSONDecodeError:
|
||||
return JsonResponse(
|
||||
{
|
||||
@ -45,7 +45,7 @@ def get_from_html(html_text, url):
|
||||
for i in items:
|
||||
md_json = json.loads(i.json())
|
||||
if 'schema.org/Recipe' in str(md_json['type']):
|
||||
return find_recipe_json(md_json['properties'], url)
|
||||
return JsonResponse(find_recipe_json(md_json['properties'], url))
|
||||
|
||||
return JsonResponse(
|
||||
{
|
||||
@ -173,7 +173,8 @@ def find_recipe_json(ld_json, url):
|
||||
else:
|
||||
ld_json['recipeInstructions'] = ''
|
||||
|
||||
ld_json['recipeInstructions'] += '\n\n' + _('Imported from') + ' ' + url
|
||||
if url != '':
|
||||
ld_json['recipeInstructions'] += '\n\n' + _('Imported from') + ' ' + url
|
||||
|
||||
if 'image' in ld_json:
|
||||
# check if list of images is returned, take first if so
|
||||
@ -232,4 +233,4 @@ def find_recipe_json(ld_json, url):
|
||||
]:
|
||||
ld_json.pop(key, None)
|
||||
|
||||
return JsonResponse(ld_json)
|
||||
return ld_json
|
||||
|
@ -2,12 +2,14 @@ import datetime
|
||||
import uuid
|
||||
|
||||
from io import BytesIO, StringIO
|
||||
from zipfile import ZipFile
|
||||
from zipfile import ZipFile, BadZipFile
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.files import File
|
||||
from django.http import HttpResponseRedirect, HttpResponse
|
||||
from django.urls import reverse
|
||||
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.translation import gettext as _
|
||||
from cookbook.models import Keyword
|
||||
|
||||
|
||||
@ -22,8 +24,8 @@ class Integration:
|
||||
"""
|
||||
self.request = request
|
||||
self.keyword = Keyword.objects.create(
|
||||
name=f'Import {datetime.datetime.now()}',
|
||||
description=f'Imported by {request.user.get_user_name()} on {datetime.datetime.now()}',
|
||||
name=f'Import {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}.{datetime.datetime.now().strftime("%S")}',
|
||||
description=f'Imported by {request.user.get_user_name()} at {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}',
|
||||
icon='📥'
|
||||
)
|
||||
|
||||
@ -67,11 +69,18 @@ class Integration:
|
||||
:param files: List of in memory files
|
||||
:return: HttpResponseRedirect to the recipe search showing all imported recipes
|
||||
"""
|
||||
for f in files:
|
||||
import_zip = ZipFile(f.file)
|
||||
for z in import_zip.namelist():
|
||||
recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z)))
|
||||
recipe.keywords.add(self.keyword)
|
||||
try:
|
||||
for f in files:
|
||||
if '.zip' in f.name:
|
||||
import_zip = ZipFile(f.file)
|
||||
for z in import_zip.namelist():
|
||||
recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z)))
|
||||
recipe.keywords.add(self.keyword)
|
||||
else:
|
||||
recipe = self.get_recipe_from_file(f.file)
|
||||
recipe.keywords.add(self.keyword)
|
||||
except BadZipFile:
|
||||
messages.add_message(self.request, messages.ERROR, _('Importer expected a .zip file. Did you choose the correct importer type for your data ?'))
|
||||
|
||||
return HttpResponseRedirect(reverse('view_search') + '?keywords=' + str(self.keyword.pk))
|
||||
|
||||
|
36
cookbook/integration/paprika.py
Normal file
36
cookbook/integration/paprika.py
Normal file
@ -0,0 +1,36 @@
|
||||
import json
|
||||
|
||||
import microdata
|
||||
|
||||
from cookbook.helper.recipe_url_import import find_recipe_json
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Food, Ingredient, Unit
|
||||
|
||||
|
||||
class Paprika(Integration):
|
||||
|
||||
def get_file_from_recipe(self, recipe):
|
||||
raise NotImplementedError('Method not implemented in storage integration')
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
html_text = file.getvalue().decode("utf-8")
|
||||
|
||||
items = microdata.get_items(html_text)
|
||||
for i in items:
|
||||
md_json = json.loads(i.json())
|
||||
if 'schema.org/Recipe' in str(md_json['type']):
|
||||
recipe_json = find_recipe_json(md_json['properties'], '')
|
||||
recipe = Recipe.objects.create(name=recipe_json['name'].strip(), created_by=self.request.user, internal=True)
|
||||
step = Step.objects.create(
|
||||
instruction=recipe_json['recipeInstructions']
|
||||
)
|
||||
|
||||
for ingredient in recipe_json['recipeIngredient']:
|
||||
f, created = Food.objects.get_or_create(name=ingredient['ingredient']['text'])
|
||||
u, created = Unit.objects.get_or_create(name=ingredient['unit']['text'])
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=ingredient['amount'], note=ingredient['note']
|
||||
))
|
||||
|
||||
recipe.steps.add(step)
|
||||
return recipe
|
@ -1,15 +1,21 @@
|
||||
import re
|
||||
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from cookbook.forms import ExportForm, ExportForm, ImportForm
|
||||
from cookbook.forms import ExportForm, ImportForm, ImportExportBase
|
||||
from cookbook.helper.permission_helper import group_required
|
||||
from cookbook.integration.default import Default
|
||||
from cookbook.integration.paprika import Paprika
|
||||
from cookbook.models import Recipe
|
||||
|
||||
|
||||
def get_integration(request, export_type):
|
||||
return Default(request)
|
||||
if export_type == ImportExportBase.DEFAULT:
|
||||
return Default(request)
|
||||
if export_type == ImportExportBase.PAPRIKA:
|
||||
return Paprika(request)
|
||||
|
||||
|
||||
@group_required('user')
|
||||
@ -17,8 +23,11 @@ def import_recipe(request):
|
||||
if request.method == "POST":
|
||||
form = ImportForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
integration = Default(request)
|
||||
return integration.do_import(request.FILES.getlist('files'))
|
||||
try:
|
||||
integration = get_integration(request, form.cleaned_data['type'])
|
||||
return integration.do_import(request.FILES.getlist('files'))
|
||||
except NotImplementedError:
|
||||
messages.add_message(request, messages.ERROR, _('Importing is not implemented for this provider'))
|
||||
else:
|
||||
form = ImportForm()
|
||||
|
||||
@ -30,8 +39,12 @@ def export_recipe(request):
|
||||
if request.method == "POST":
|
||||
form = ExportForm(request.POST)
|
||||
if form.is_valid():
|
||||
integration = Default(request)
|
||||
return integration.do_export(form.cleaned_data['recipes'])
|
||||
try:
|
||||
integration = get_integration(request, form.cleaned_data['type'])
|
||||
return integration.do_export(form.cleaned_data['recipes'])
|
||||
except NotImplementedError:
|
||||
messages.add_message(request, messages.ERROR, _('Exporting is not implemented for this provider'))
|
||||
|
||||
else:
|
||||
form = ExportForm()
|
||||
recipe = request.GET.get('r')
|
||||
|
@ -1,6 +1,6 @@
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime
|
||||
from uuid import UUID
|
||||
|
||||
from django.conf import settings
|
||||
@ -11,7 +11,7 @@ from django.contrib.auth.password_validation import validate_password
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import IntegrityError
|
||||
from django.db.models import Avg, Q
|
||||
from django.http import HttpResponseRedirect, FileResponse, HttpResponse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, render, redirect
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils import timezone
|
||||
@ -22,9 +22,8 @@ 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, ImportForm, ExportForm)
|
||||
UserPreferenceForm)
|
||||
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,
|
||||
RecipeBook, RecipeBookEntry, ViewLog, ShoppingList)
|
||||
from cookbook.tables import (CookLogTable, RecipeTable, RecipeTableSmall,
|
||||
|
@ -19,4 +19,13 @@ The default integration is the build in (and preferred) way to import and export
|
||||
It is maintained with new fields added and contains all data to transfer your recipes from one installation to another.
|
||||
|
||||
It is also one of the few recipe formats that is actually structured in a way that allows for
|
||||
easy machine readability if you want to use the data for any other purpose.
|
||||
easy machine readability if you want to use the data for any other purpose.
|
||||
|
||||
## Paprika
|
||||
Paprika can create two types of export. The first is a proprietary `.paprikarecipes` file in some kind of binarized format.
|
||||
The second one is HTML files containing at least a bit of microdata.
|
||||
|
||||
If you want to import your Paprika recipes create a html export. Then import the individual recipes HTML files.
|
||||
Due to the lack of structure not all fields can be imported.
|
||||
Even tough images are present in the export they cannot be imported atm. This is technically possible and might be
|
||||
added in the future.
|
Loading…
Reference in New Issue
Block a user