added basic exporting capability
This commit is contained in:
@ -100,6 +100,13 @@ class ShoppingForm(forms.Form):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ExportForm(forms.Form):
|
||||||
|
recipe = forms.ModelChoiceField(
|
||||||
|
queryset=Recipe.objects.filter(internal=True).all(),
|
||||||
|
widget=SelectWidget
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class UnitMergeForm(forms.Form):
|
class UnitMergeForm(forms.Form):
|
||||||
prefix = 'unit'
|
prefix = 'unit'
|
||||||
|
|
||||||
|
@ -154,8 +154,8 @@ class Ingredient(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class RecipeIngredient(models.Model):
|
class RecipeIngredient(models.Model):
|
||||||
ingredient = models.ForeignKey(Ingredient, on_delete=models.PROTECT)
|
|
||||||
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
|
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
|
||||||
|
ingredient = models.ForeignKey(Ingredient, on_delete=models.PROTECT)
|
||||||
unit = models.ForeignKey(Unit, on_delete=models.PROTECT)
|
unit = models.ForeignKey(Unit, on_delete=models.PROTECT)
|
||||||
amount = models.DecimalField(default=0, decimal_places=2, max_digits=16)
|
amount = models.DecimalField(default=0, decimal_places=2, max_digits=16)
|
||||||
note = models.CharField(max_length=64, null=True, blank=True)
|
note = models.CharField(max_length=64, null=True, blank=True)
|
||||||
|
70
cookbook/templates/export.html
Normal file
70
cookbook/templates/export.html
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %}{% trans 'Export Recipes' %}{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
{{ form.media }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-md-12">
|
||||||
|
<form action="." method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
<button class="btn btn-success" type="submit"><i class="fas fa-file-export"></i> {% trans 'Export' %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if export %}
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-md-12">
|
||||||
|
<label for="id_export">
|
||||||
|
{% trans 'Exported Recipe' %}</label>
|
||||||
|
<textarea id="id_export" class="form-control" rows="12">
|
||||||
|
{{ export }}
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-md-12 text-center">
|
||||||
|
<button class="btn btn-success" onclick="copy()" style="width: 15vw" data-toggle="tooltip"
|
||||||
|
data-placement="right" title="{% trans 'Copy to clipboard' %}" id="id_btn_copy"
|
||||||
|
onmouseout="resetTooltip()"><i
|
||||||
|
class="far fa-copy"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function copy() {
|
||||||
|
let json = $('#id_export');
|
||||||
|
|
||||||
|
json.select();
|
||||||
|
|
||||||
|
$('#id_btn_copy').attr('data-original-title', '{% trans 'Copied!' %}').tooltip('show');
|
||||||
|
|
||||||
|
document.execCommand("copy");
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetTooltip() {
|
||||||
|
setTimeout(function () {
|
||||||
|
$('#id_btn_copy').attr('data-original-title', '{% trans 'Copy list to clipboard' %}');
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
10
cookbook/templates/import.html
Normal file
10
cookbook/templates/import.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %}{% trans 'Import Recipes' %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -34,7 +34,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col col-md-12 text-center">
|
<div class="col col-md-12 text-center">
|
||||||
<button class="btn btn-success" onclick="copy()" style="width: 15vw" data-toggle="tooltip"
|
<button class="btn btn-success" onclick="copy()" style="width: 15vw" data-toggle="tooltip"
|
||||||
data-placement="top" title="{% trans 'Copy list to clipboard' %}" id="id_btn_copy" onmouseout="resetTooltip()"><i
|
data-placement="right" title="{% trans 'Copy list to clipboard' %}" id="id_btn_copy" onmouseout="resetTooltip()"><i
|
||||||
class="far fa-copy"></i></button>
|
class="far fa-copy"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@ from pydoc import locate
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from .views import *
|
from .views import *
|
||||||
from cookbook.views import api
|
from cookbook.views import api, import_export
|
||||||
from cookbook.helper import dal
|
from cookbook.helper import dal
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@ -14,6 +14,9 @@ urlpatterns = [
|
|||||||
path('shopping/', views.shopping_list, name='view_shopping'),
|
path('shopping/', views.shopping_list, name='view_shopping'),
|
||||||
path('settings/', views.settings, name='view_settings'),
|
path('settings/', views.settings, name='view_settings'),
|
||||||
|
|
||||||
|
path('import/', import_export.import_recipe, name='view_import'),
|
||||||
|
path('export/', import_export.export_recipe, name='view_export'),
|
||||||
|
|
||||||
path('view/recipe/<int:pk>', views.recipe_view, name='view_recipe'),
|
path('view/recipe/<int:pk>', views.recipe_view, name='view_recipe'),
|
||||||
|
|
||||||
path('new/recipe_import/<int:import_id>/', new.create_new_external_recipe, name='new_recipe_import'),
|
path('new/recipe_import/<int:import_id>/', new.create_new_external_recipe, name='new_recipe_import'),
|
||||||
|
44
cookbook/views/import_export.py
Normal file
44
cookbook/views/import_export.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
from django.core import serializers
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
from cookbook.forms import ExportForm
|
||||||
|
from cookbook.models import Recipe, Ingredient, RecipeIngredient, Unit
|
||||||
|
|
||||||
|
|
||||||
|
def import_recipe(request):
|
||||||
|
return render(request, 'import.html', {})
|
||||||
|
|
||||||
|
|
||||||
|
def export_recipe(request):
|
||||||
|
# TODO filter internal only
|
||||||
|
context = {}
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = ExportForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
recipe = form.cleaned_data['recipe']
|
||||||
|
|
||||||
|
export = {
|
||||||
|
'recipe': {'name': recipe.name, 'instructions': recipe.instructions, 'working_time': recipe.working_time, 'waiting_time': recipe.working_time},
|
||||||
|
'units': [],
|
||||||
|
'ingredients': [],
|
||||||
|
'recipe_ingredients': []
|
||||||
|
}
|
||||||
|
|
||||||
|
for ri in RecipeIngredient.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({'ingredient': ri.ingredient.name, 'unit': ri.unit.name, 'amount': float(ri.amount), 'note': ri.note})
|
||||||
|
|
||||||
|
context['export'] = json.dumps(export, indent=4)
|
||||||
|
else:
|
||||||
|
form = ExportForm()
|
||||||
|
|
||||||
|
context['form'] = form
|
||||||
|
|
||||||
|
return render(request, 'export.html', context)
|
Reference in New Issue
Block a user