super basic edit view
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from cookbook.models import MealPlan, MealType, Recipe, ViewLog, UserPreference, Storage, Sync, SyncLog, Keyword, Unit, Ingredient, Comment, RecipeImport, RecipeBook, RecipeBookEntry, ShareLink, CookLog, Food
|
from cookbook.models import MealPlan, MealType, Recipe, ViewLog, UserPreference, Storage, Sync, SyncLog, Keyword, Unit, Ingredient, Comment, RecipeImport, RecipeBook, RecipeBookEntry, ShareLink, CookLog, Food, Step
|
||||||
from cookbook.templatetags.custom_tags import markdown
|
from cookbook.templatetags.custom_tags import markdown
|
||||||
|
|
||||||
|
|
||||||
@ -42,12 +42,6 @@ class KeywordSerializer(serializers.ModelSerializer):
|
|||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class RecipeSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Recipe
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
|
|
||||||
class UnitSerializer(serializers.ModelSerializer):
|
class UnitSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Unit
|
model = Unit
|
||||||
@ -61,14 +55,28 @@ class FoodSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class IngredientSerializer(serializers.ModelSerializer):
|
class IngredientSerializer(serializers.ModelSerializer):
|
||||||
|
food = FoodSerializer(read_only=True)
|
||||||
|
unit = UnitSerializer(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Ingredient
|
model = Ingredient
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class CommentSerializer(serializers.ModelSerializer):
|
class StepSerializer(serializers.ModelSerializer):
|
||||||
|
ingredients = IngredientSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Comment
|
model = Step
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeSerializer(serializers.ModelSerializer):
|
||||||
|
steps = StepSerializer(many=True, read_only=True)
|
||||||
|
keywords = KeywordSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Recipe
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
@ -78,6 +86,12 @@ class RecipeImportSerializer(serializers.ModelSerializer):
|
|||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class CommentSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Comment
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class RecipeBookSerializer(serializers.ModelSerializer):
|
class RecipeBookSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RecipeBook
|
model = RecipeBook
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load crispy_forms_tags %}
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load custom_tags %}
|
{% load custom_tags %}
|
||||||
{% load theming_tags %}
|
{% load theming_tags %}
|
||||||
@ -8,8 +7,11 @@
|
|||||||
{% block title %}{% trans 'Edit Recipe' %}{% endblock %}
|
{% block title %}{% trans 'Edit Recipe' %}{% endblock %}
|
||||||
|
|
||||||
{% block extra_head %}
|
{% block extra_head %}
|
||||||
<script src="{% static 'tabulator/tabulator.min.js' %}"></script>
|
|
||||||
<link rel="stylesheet" href="{% tabulator_theme_url request %}"/>
|
{% include 'include/vue_base.html' %}
|
||||||
|
|
||||||
|
<script src="{% static 'js/vue-multiselect.min.js' %}"></script>
|
||||||
|
<link rel="stylesheet" href="{% static 'css/vue-multiselect.min.css' %}">
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@ -17,219 +19,101 @@
|
|||||||
|
|
||||||
<h3>{% trans 'Edit Recipe' %}</h3>
|
<h3>{% trans 'Edit Recipe' %}</h3>
|
||||||
|
|
||||||
<form action="." method="post" enctype="multipart/form-data" id="id_form">
|
<div id="app">
|
||||||
{% csrf_token %}
|
<template v-if="recipe">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label for="id_name"> {% trans 'Name' %}</label>
|
||||||
|
<input class="form-control" id="id_name" v-model="recipe.name">
|
||||||
|
|
||||||
{% for field in form %}
|
|
||||||
<div class="fieldWrapper">
|
|
||||||
{{ field|as_crispy_field }}
|
|
||||||
</div>
|
</div>
|
||||||
{% if field.name == 'name' %}
|
|
||||||
<label>{% trans 'Ingredients' %}</label>
|
|
||||||
{{ form.ingredients.errors }}
|
|
||||||
<div id="ingredients-table"></div>
|
|
||||||
<br>
|
|
||||||
<div class="table-controls" style="text-align: center">
|
|
||||||
<button class="btn btn-success" id="new_empty" type="button" style="min-width: 20vw"><i
|
|
||||||
class="fas fa-plus-circle"></i></button>
|
|
||||||
<button class="btn btn-warning" id="new_header" type="button" data-toggle="tooltip"
|
|
||||||
data-placement="top" title="{% trans 'Insert a header between the ingredients.' %}"><i class="fas fa-heading"></i></button>
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-secondary" data-container="body" data-toggle="popover"
|
|
||||||
data-placement="right" data-html="true" data-trigger="focus"
|
|
||||||
data-content="{% trans 'Use <b>Ctrl</b>+<b>Space</b> to insert new Ingredient!<br/>You can also save the recipe using <b>Ctrl</b>+<b>Shift</b>+<b>S</b>.' %}">
|
|
||||||
<i class="fas fa-question"></i>
|
|
||||||
</button>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
<br/>
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<hr>
|
<div class="row">
|
||||||
<button class="btn btn-success" type="submit"><i class="fas fa-save"></i> {% trans 'Save' %}</button>
|
<div class="col-md-6">
|
||||||
<a href="{% delete_url form.instance|get_class form.instance.pk %}"
|
Image Edit Placeholder
|
||||||
class="btn btn-danger"><i class="fas fa-trash-alt"></i> {% trans 'Delete' %}</a>
|
</div>
|
||||||
{% if view_url %}
|
<div class="col-md-6">
|
||||||
<a href="{{ view_url }}" class="btn btn-info"><i class="far fa-eye"></i> {% trans 'View' %}</a>
|
<label for="id_name"> {% trans 'Preperation Time' %}</label>
|
||||||
{% endif %}
|
<input class="form-control" id="id_prep_time" v-model="recipe.working_time">
|
||||||
{% if form.instance.storage %}
|
|
||||||
<a href="{% url 'delete_recipe_source' form.instance.pk %}" class="btn btn-warning"><i
|
<label for="id_name"> {% trans 'Waiting Time' %}</label>
|
||||||
class="fas fa-exclamation-triangle"></i> {% trans 'Delete original file' %}</a>
|
<input class="form-control" id="id_wait_time" v-model="recipe.waiting_time">
|
||||||
{% endif %}
|
|
||||||
</form>
|
<label for="id_name"> {% trans 'Keywords' %}</label>
|
||||||
|
<multiselect
|
||||||
|
v-model="recipe.keywords"
|
||||||
|
:options="keywords"
|
||||||
|
:close-on-select="false"
|
||||||
|
:clear-on-select="true"
|
||||||
|
:hide-selected="true"
|
||||||
|
:preserve-search="true"
|
||||||
|
placeholder="{% trans 'Select one' %}"
|
||||||
|
label="name"
|
||||||
|
track-by="id"
|
||||||
|
id="id_keywords"
|
||||||
|
:multiple="true"
|
||||||
|
:loading="keywords_loading"
|
||||||
|
@search-change="searchKeywords">
|
||||||
|
</multiselect>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
|
let csrftoken = Cookies.get('csrftoken');
|
||||||
|
Vue.http.headers.common['X-CSRFToken'] = csrftoken;
|
||||||
|
|
||||||
$(function () {
|
Vue.component('vue-multiselect', window.VueMultiselect.default)
|
||||||
$('[data-toggle="popover"]').popover()
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.popover-dismiss').popover({
|
let app = new Vue({
|
||||||
trigger: 'focus'
|
components: {
|
||||||
});
|
Multiselect: window.VueMultiselect.default
|
||||||
|
},
|
||||||
let select2UnitEditor = function (cell, onRendered, success, cancel, editorParams) {
|
delimiters: ['[[', ']]'],
|
||||||
return select2Editor(cell, onRendered, success, cancel, editorParams, '{% url 'dal_unit' %}')
|
el: '#app',
|
||||||
};
|
data: {
|
||||||
|
recipe: undefined,
|
||||||
let select2IngredientEditor = function (cell, onRendered, success, cancel, editorParams) {
|
keywords: [],
|
||||||
return select2Editor(cell, onRendered, success, cancel, editorParams, '{% url 'dal_food' %}')
|
keywords_loading: false,
|
||||||
};
|
},
|
||||||
|
directives: {
|
||||||
let select2Editor = function (cell, onRendered, success, cancel, editorParams, url) {
|
tabindex: {
|
||||||
|
inserted(el) {
|
||||||
let editor = document.createElement("select");
|
el.setAttribute('tabindex', 0);
|
||||||
editor.setAttribute("class", "form-control");
|
|
||||||
editor.setAttribute("style", "height: 100%; color: #00ff00");
|
|
||||||
|
|
||||||
onRendered(function () {
|
|
||||||
let select_2 = $(editor);
|
|
||||||
|
|
||||||
select_2.select2({
|
|
||||||
tags: true,
|
|
||||||
ajax: {
|
|
||||||
url: url,
|
|
||||||
dataType: 'json'
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
select_2.select2('open');
|
|
||||||
|
|
||||||
select_2.on('select2:select', function (e) {
|
|
||||||
success(e.params.data.text);
|
|
||||||
});
|
|
||||||
|
|
||||||
select_2.on('select2:close', function (e) {
|
|
||||||
if (e.target.textContent === "") {
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//add editor to cell
|
|
||||||
return editor;
|
|
||||||
};
|
|
||||||
|
|
||||||
//converts multiselct in recipe edit to searchable multiselect
|
|
||||||
//shitty solution that needs to be redone at some point
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#id_keywords').select2();
|
|
||||||
|
|
||||||
let ingredients = {{ ingredients|safe }}
|
|
||||||
|
|
||||||
ingredients.forEach(function (cur, i) {
|
|
||||||
cur.delete = false
|
|
||||||
});
|
|
||||||
|
|
||||||
let data = ingredients;
|
|
||||||
|
|
||||||
let table = new Tabulator("#ingredients-table", {
|
|
||||||
index: "id",
|
|
||||||
layout: "fitColumns",
|
|
||||||
reactiveData: true,
|
|
||||||
data: data,
|
|
||||||
movableRows: true,
|
|
||||||
headerSort: false,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
title: "<i class='fas fa-sort'></i>",
|
|
||||||
rowHandle: true,
|
|
||||||
formatter: "handle",
|
|
||||||
headerSort: false,
|
|
||||||
frozen: true,
|
|
||||||
width: 36,
|
|
||||||
minWidth: 36
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "{% trans 'Ingredient' %}",
|
|
||||||
field: "ingredient__name",
|
|
||||||
validator: "required",
|
|
||||||
editor: select2IngredientEditor
|
|
||||||
},
|
|
||||||
{title: "{% trans 'Amount' %}", field: "amount", validator: "required", editor: "number"},
|
|
||||||
{
|
|
||||||
title: "{% trans 'Unit' %}",
|
|
||||||
field: "unit__name",
|
|
||||||
validator: "required",
|
|
||||||
editor: select2UnitEditor
|
|
||||||
},
|
|
||||||
{title: "{% trans 'Note' %}", field: "note", editor: "input"},
|
|
||||||
{
|
|
||||||
formatter: function (cell, formatterParams) {
|
|
||||||
return "<span style='color:red'><i class=\"fas fa-trash-alt\"></i></span>"
|
|
||||||
},
|
|
||||||
align: "center",
|
|
||||||
title: "{% trans 'Delete' %}",
|
|
||||||
headerSort: false,
|
|
||||||
cellClick: function (e, cell) {
|
|
||||||
if (confirm('{% trans 'Are you sure that you want to delete this ingredient?' %}'))
|
|
||||||
cell.getRow().delete();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{title: "id", field: "id", visible: false}
|
mounted: function () {
|
||||||
],
|
this.loadRecipe()
|
||||||
cellClick: function (e, cell) {
|
|
||||||
if (cell._cell.column.definition.editor === "input") {
|
|
||||||
input = cell.getElement().childNodes[0];
|
|
||||||
input.focus();
|
|
||||||
input.select();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
methods: {
|
||||||
|
loadRecipe: function () {
|
||||||
// save ingredient data before submitting form
|
this.$http.get("{% url 'api:recipe-list' %}{{ recipe.pk }}").then((response) => {
|
||||||
$('#id_form').submit(function () {
|
this.recipe = response.data;
|
||||||
$('#id_ingredients').val(JSON.stringify(table.getData()));
|
this.loading = false
|
||||||
return true;
|
}).catch((err) => {
|
||||||
});
|
this.error = err.data
|
||||||
|
this.loading = false
|
||||||
// load initial value
|
console.log(err)
|
||||||
$('#id_ingredients').val(JSON.stringify(data));
|
|
||||||
|
|
||||||
function addIngredientRow() {
|
|
||||||
data.push({
|
|
||||||
ingredient__name: "{% trans 'Ingredient' %}",
|
|
||||||
amount: "100",
|
|
||||||
unit__name: "{{ request.user.userpreference.default_unit }}",
|
|
||||||
note: "",
|
|
||||||
id: Math.floor(Math.random() * 10000000),
|
|
||||||
delete: false,
|
|
||||||
});
|
|
||||||
input = table.rowManager.rows[((table.rowManager.rows).length) - 1].cells[1].getElement()
|
|
||||||
input.focus();
|
|
||||||
input.select();
|
|
||||||
}
|
|
||||||
|
|
||||||
function addHeaderRow(type) {
|
|
||||||
data.push({
|
|
||||||
ingredient__name: '{% trans 'Header' %}',
|
|
||||||
amount: "0",
|
|
||||||
unit__name: "Special:Header",
|
|
||||||
note: "{% trans 'write header here' %}",
|
|
||||||
id: Math.floor(Math.random() * 10000000),
|
|
||||||
delete: false,
|
|
||||||
});
|
|
||||||
input = table.rowManager.rows[((table.rowManager.rows).length) - 1].cells[4].getElement()
|
|
||||||
input.focus();
|
|
||||||
input.select();
|
|
||||||
}
|
|
||||||
|
|
||||||
document.onkeyup = function (e) {
|
|
||||||
if (e.shiftKey && e.ctrlKey && (e.which === 83 || e.keyCode === 83)) {
|
|
||||||
$('#id_form').submit()
|
|
||||||
} else if (e.ctrlKey && (e.which === 83 || e.keyCode === 32)) {
|
|
||||||
addIngredientRow();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("new_empty").addEventListener("click", addIngredientRow);
|
|
||||||
document.getElementById("new_header").addEventListener("click", addHeaderRow);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
$('[data-toggle="tooltip"]').tooltip()
|
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
searchKeywords: function (query) {
|
||||||
|
this.keywords_loading = true
|
||||||
|
this.$http.get("{% url 'api:keyword-list' %}" + '?query=' + query).then((response) => {
|
||||||
|
this.keywords = response.data;
|
||||||
|
this.keywords_loading = false
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -10,9 +10,12 @@ from cookbook.helper import dal
|
|||||||
|
|
||||||
router = routers.DefaultRouter()
|
router = routers.DefaultRouter()
|
||||||
router.register(r'user-preference', api.UserPreferenceViewSet)
|
router.register(r'user-preference', api.UserPreferenceViewSet)
|
||||||
router.register(r'recipe', api.RecipeViewSet)
|
router.register(r'unit', api.UnitViewSet)
|
||||||
router.register(r'food', api.FoodViewSet)
|
router.register(r'food', api.FoodViewSet)
|
||||||
router.register(r'recipe-ingredient', api.IngredientViewSet)
|
router.register(r'step', api.StepViewSet)
|
||||||
|
router.register(r'recipe', api.RecipeViewSet)
|
||||||
|
router.register(r'keyword', api.KeywordViewSet)
|
||||||
|
router.register(r'ingredient', api.IngredientViewSet)
|
||||||
router.register(r'meal-plan', api.MealPlanViewSet)
|
router.register(r'meal-plan', api.MealPlanViewSet)
|
||||||
router.register(r'meal-type', api.MealTypeViewSet)
|
router.register(r'meal-type', api.MealTypeViewSet)
|
||||||
router.register(r'view-log', api.ViewLogViewSet)
|
router.register(r'view-log', api.ViewLogViewSet)
|
||||||
|
@ -18,10 +18,11 @@ from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, ListMode
|
|||||||
|
|
||||||
from cookbook.helper.permission_helper import group_required, CustomIsOwner, CustomIsAdmin, CustomIsUser
|
from cookbook.helper.permission_helper import group_required, CustomIsOwner, CustomIsAdmin, CustomIsUser
|
||||||
from cookbook.helper.recipe_url_import import get_from_html
|
from cookbook.helper.recipe_url_import import get_from_html
|
||||||
from cookbook.models import Recipe, Sync, Storage, CookLog, MealPlan, MealType, ViewLog, UserPreference, RecipeBook, Ingredient, Food
|
from cookbook.models import Recipe, Sync, Storage, CookLog, MealPlan, MealType, ViewLog, UserPreference, RecipeBook, Ingredient, Food, Step, Keyword
|
||||||
from cookbook.provider.dropbox import Dropbox
|
from cookbook.provider.dropbox import Dropbox
|
||||||
from cookbook.provider.nextcloud import Nextcloud
|
from cookbook.provider.nextcloud import Nextcloud
|
||||||
from cookbook.serializer import MealPlanSerializer, MealTypeSerializer, RecipeSerializer, ViewLogSerializer, UserNameSerializer, UserPreferenceSerializer, RecipeBookSerializer, IngredientSerializer, FoodSerializer
|
from cookbook.serializer import MealPlanSerializer, MealTypeSerializer, RecipeSerializer, ViewLogSerializer, UserNameSerializer, UserPreferenceSerializer, RecipeBookSerializer, IngredientSerializer, FoodSerializer, StepSerializer, \
|
||||||
|
KeywordSerializer
|
||||||
|
|
||||||
|
|
||||||
class UserNameViewSet(viewsets.ModelViewSet):
|
class UserNameViewSet(viewsets.ModelViewSet):
|
||||||
@ -110,13 +111,37 @@ class MealTypeViewSet(viewsets.ModelViewSet):
|
|||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class UnitViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Food.objects.all()
|
||||||
|
serializer_class = FoodSerializer
|
||||||
|
permission_classes = [CustomIsUser]
|
||||||
|
|
||||||
|
|
||||||
|
class FoodViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Food.objects.all()
|
||||||
|
serializer_class = FoodSerializer
|
||||||
|
permission_classes = [CustomIsUser]
|
||||||
|
|
||||||
|
|
||||||
|
class IngredientViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Ingredient.objects.all()
|
||||||
|
serializer_class = IngredientSerializer
|
||||||
|
permission_classes = [CustomIsUser]
|
||||||
|
|
||||||
|
|
||||||
|
class StepViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Step.objects.all()
|
||||||
|
serializer_class = StepSerializer
|
||||||
|
permission_classes = [CustomIsUser]
|
||||||
|
|
||||||
|
|
||||||
class RecipeViewSet(viewsets.ModelViewSet):
|
class RecipeViewSet(viewsets.ModelViewSet):
|
||||||
"""
|
"""
|
||||||
list:
|
list:
|
||||||
optional parameters
|
optional parameters
|
||||||
|
|
||||||
- **query**: search a recipe for a string contained in the recipe name (case in-sensitive)
|
- **query**: search recipes for a string contained in the recipe name (case in-sensitive)
|
||||||
- **limit**: limits the amount of returned recipes
|
- **limit**: limits the amount of returned results
|
||||||
"""
|
"""
|
||||||
queryset = Recipe.objects.all()
|
queryset = Recipe.objects.all()
|
||||||
serializer_class = RecipeSerializer
|
serializer_class = RecipeSerializer
|
||||||
@ -134,16 +159,28 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
|||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class IngredientViewSet(viewsets.ModelViewSet):
|
class KeywordViewSet(viewsets.ModelViewSet):
|
||||||
queryset = Ingredient.objects.all()
|
"""
|
||||||
serializer_class = IngredientSerializer
|
list:
|
||||||
|
optional parameters
|
||||||
|
|
||||||
|
- **query**: search keywords for a string contained in the keyword name (case in-sensitive)
|
||||||
|
- **limit**: limits the amount of returned results
|
||||||
|
"""
|
||||||
|
queryset = Keyword.objects.all()
|
||||||
|
serializer_class = KeywordSerializer
|
||||||
permission_classes = [CustomIsUser]
|
permission_classes = [CustomIsUser]
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = Keyword.objects.all()
|
||||||
|
query = self.request.query_params.get('query', None)
|
||||||
|
if query is not None:
|
||||||
|
queryset = queryset.filter(name__icontains=query)
|
||||||
|
|
||||||
class FoodViewSet(viewsets.ModelViewSet):
|
limit = self.request.query_params.get('limit', None)
|
||||||
queryset = Food.objects.all()
|
if limit is not None:
|
||||||
serializer_class = FoodSerializer
|
queryset = queryset[:int(limit)]
|
||||||
permission_classes = [CustomIsUser]
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class ViewLogViewSet(viewsets.ModelViewSet):
|
class ViewLogViewSet(viewsets.ModelViewSet):
|
||||||
|
@ -124,14 +124,8 @@ def internal_recipe_update(request, pk):
|
|||||||
else:
|
else:
|
||||||
messages.add_message(request, messages.ERROR, _('There was an error saving this recipe!'))
|
messages.add_message(request, messages.ERROR, _('There was an error saving this recipe!'))
|
||||||
status = 403
|
status = 403
|
||||||
else:
|
|
||||||
form = InternalRecipeForm(instance=recipe_instance)
|
|
||||||
|
|
||||||
ingredients = Ingredient.objects.select_related('unit__name', 'food__name').filter(recipe=recipe_instance).values('food__name', 'unit__name', 'amount', 'note').order_by('id')
|
return render(request, 'forms/edit_internal_recipe.html', {'recipe': recipe_instance})
|
||||||
|
|
||||||
return render(request, 'forms/edit_internal_recipe.html',
|
|
||||||
{'form': form, 'ingredients': json.dumps(list(ingredients)),
|
|
||||||
'view_url': reverse('view_recipe', args=[pk])}, status=status)
|
|
||||||
|
|
||||||
|
|
||||||
class SyncUpdate(GroupRequiredMixin, UpdateView):
|
class SyncUpdate(GroupRequiredMixin, UpdateView):
|
||||||
|
Reference in New Issue
Block a user