From f6f1590f02a9ce400807a2ab29678053dc80cb99 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Wed, 28 Dec 2022 11:01:40 +0100 Subject: [PATCH 01/20] Start App Recipes --- recipes/__init__.py | 0 recipes/admin.py | 3 +++ recipes/apps.py | 6 ++++++ recipes/migrations/__init__.py | 0 recipes/models.py | 3 +++ recipes/tests.py | 3 +++ recipes/views.py | 3 +++ stadlbauer/settings.py | 1 + 8 files changed, 19 insertions(+) create mode 100644 recipes/__init__.py create mode 100644 recipes/admin.py create mode 100644 recipes/apps.py create mode 100644 recipes/migrations/__init__.py create mode 100644 recipes/models.py create mode 100644 recipes/tests.py create mode 100644 recipes/views.py diff --git a/recipes/__init__.py b/recipes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/recipes/admin.py b/recipes/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/recipes/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/recipes/apps.py b/recipes/apps.py new file mode 100644 index 0000000..1d53980 --- /dev/null +++ b/recipes/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class RecipesConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'recipes' diff --git a/recipes/migrations/__init__.py b/recipes/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/recipes/models.py b/recipes/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/recipes/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/recipes/tests.py b/recipes/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/recipes/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/recipes/views.py b/recipes/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/recipes/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/stadlbauer/settings.py b/stadlbauer/settings.py index 3298df5..b4838c6 100644 --- a/stadlbauer/settings.py +++ b/stadlbauer/settings.py @@ -50,6 +50,7 @@ ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ + 'recipes.apps.RecipesConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', From f8d5ca0e833fb2850d2cea82f25daba1aa9dc8e2 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 11 Mar 2023 19:13:38 +0100 Subject: [PATCH 02/20] Add recipes/ url pattern --- stadlbauer/urls.py | 1 + 1 file changed, 1 insertion(+) diff --git a/stadlbauer/urls.py b/stadlbauer/urls.py index 62c9e6b..f0a68b1 100644 --- a/stadlbauer/urls.py +++ b/stadlbauer/urls.py @@ -38,6 +38,7 @@ from . import views urlpatterns = [ path('', views.index, name='index'), + path('recipes/', include('recipes.urls')), path('admin/', admin.site.urls), path('accounts/new-user/', views.new_user, name='new-user'), path('accounts/profile/', views.profile, name='profile'), From 62b4865a26cf9ce0719a8c4beb2f78721076c7bf Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 11 Mar 2023 19:14:37 +0100 Subject: [PATCH 03/20] Add links to recipes add to nav list and index --- templates/base_main.html | 1 + templates/index.html | 3 +++ 2 files changed, 4 insertions(+) diff --git a/templates/base_main.html b/templates/base_main.html index bc17826..3ae0da7 100644 --- a/templates/base_main.html +++ b/templates/base_main.html @@ -36,6 +36,7 @@ {% endif %} diff --git a/templates/index.html b/templates/index.html index 582347c..ee4d00e 100644 --- a/templates/index.html +++ b/templates/index.html @@ -20,4 +20,7 @@ {% block title %}Barn{% endblock %} {% block main %}

Barn

+ {% endblock %} From da694d8d63273c28ad509c176000885f8515f449 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 11 Mar 2023 19:16:06 +0100 Subject: [PATCH 04/20] Add models --- recipes/models.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/recipes/models.py b/recipes/models.py index 71a8362..80a66ad 100644 --- a/recipes/models.py +++ b/recipes/models.py @@ -1,3 +1,34 @@ from django.db import models +from django.contrib.auth.models import User +from django.urls import reverse -# Create your models here. +class Recipe(models.Model): + title = models.CharField(max_length=100, null=False, blank=False) + slug = models.SlugField(unique=True) + + def __str__(self) -> str: + return self.title + + def get_absolute_url(self): + return reverse('recipe', kwargs={'slug': self.slug}) + +class Version(models.Model): + label = models.CharField(max_length=20, default='Original') + slug = models.SlugField(max_length=20, default='original') + body = models.TextField(null=True, blank=True) + user = models.ForeignKey(User, on_delete=models.PROTECT, null=False, blank=False) + author = models.CharField(max_length=30, blank=True) + recipe = models.ForeignKey(Recipe, on_delete=models.PROTECT, null=False, blank=False, related_name='versions') + + def __str__(self) -> str: + return self.recipe.title + ' - ' + self.label + + def get_absolute_url(self): + return reverse('version', kwargs={'slug_recipe': self.recipe.slug, 'slug_version': self.slug}) + +class Ingredient(models.Model): + text = models.CharField(max_length=50, null=False, blank=False) + version = models.ForeignKey(Version, on_delete=models.CASCADE, null=False, blank=False, related_name='ingredients') + + def __str__(self) -> str: + return self.text + ' for ' + str(self.version) From da7ae6151edadb5d4b5da0c3c5ae805065d1fb5d Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 11 Mar 2023 19:16:49 +0100 Subject: [PATCH 05/20] Register models to admin --- recipes/admin.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/recipes/admin.py b/recipes/admin.py index 8c38f3f..1542b98 100644 --- a/recipes/admin.py +++ b/recipes/admin.py @@ -1,3 +1,6 @@ from django.contrib import admin +from .models import Recipe, Version, Ingredient -# Register your models here. +admin.site.register(Recipe) +admin.site.register(Version) +admin.site.register(Ingredient) From 0141332d2e7c8a1ae64528e8aaa98103af083523 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 11 Mar 2023 19:17:19 +0100 Subject: [PATCH 06/20] Add forms --- recipes/forms.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 recipes/forms.py diff --git a/recipes/forms.py b/recipes/forms.py new file mode 100644 index 0000000..f02cf4d --- /dev/null +++ b/recipes/forms.py @@ -0,0 +1,37 @@ +from django.forms import ModelForm, ValidationError, modelformset_factory, BooleanField +from .models import Recipe, Version, Ingredient + +class RecipeForm(ModelForm): + class Meta: + model = Recipe + fields = ['title', 'slug'] + +class VersionForm(ModelForm): + recipe_id: int + + def __init__(self, *args, **kwargs): + placeholder = None + if 'author_placeholder' in kwargs: + placeholder = kwargs.pop('author_placeholder') + super().__init__(*args, **kwargs) + if placeholder: + self.fields['author'].widget.attrs.update({'placeholder': placeholder}) + + class Meta: + model = Version + fields = ['label', 'slug', 'body', 'author'] + + def clean_slug(self): + slug = self.cleaned_data['slug'] + if 'slug' in self.changed_data: + recipe = Recipe.objects.get(id=self.recipe_id) + if recipe.versions.filter(slug=slug).count() > 0: # type: ignore + raise ValidationError('A recipe version with this slug already exists.') + return slug + +class IngredientForm(ModelForm): + class Meta: + model = Ingredient + fields = ['text'] + +IngredientFormSet = modelformset_factory(Ingredient, fields=('text',), extra=1) From de214a9e2a3b15d68f401aa48b68501865783eb2 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 11 Mar 2023 19:18:01 +0100 Subject: [PATCH 07/20] Add HTML templates --- recipes/templates/add-recipe.html | 41 +++++++++++++++++++++++++++++ recipes/templates/add-version.html | 40 ++++++++++++++++++++++++++++ recipes/templates/edit-recipe.html | 10 +++++++ recipes/templates/edit-version.html | 40 ++++++++++++++++++++++++++++ recipes/templates/recipe.html | 12 +++++++++ recipes/templates/recipes.html | 11 ++++++++ recipes/templates/version.html | 17 ++++++++++++ 7 files changed, 171 insertions(+) create mode 100644 recipes/templates/add-recipe.html create mode 100644 recipes/templates/add-version.html create mode 100644 recipes/templates/edit-recipe.html create mode 100644 recipes/templates/edit-version.html create mode 100644 recipes/templates/recipe.html create mode 100644 recipes/templates/recipes.html create mode 100644 recipes/templates/version.html diff --git a/recipes/templates/add-recipe.html b/recipes/templates/add-recipe.html new file mode 100644 index 0000000..bd8968c --- /dev/null +++ b/recipes/templates/add-recipe.html @@ -0,0 +1,41 @@ +{% extends "base_main.html" %} +{% block title %}{{ recipe.title }}{% endblock %} +{% block main %} +
+ {%csrf_token %} + {{ recipe_form.as_div }} + + {{ version_form.as_table }} +
+ {{ ingredients_formset.management_form }} + {% for ingredient_form in ingredients_formset %} + {{ ingredient_form.as_div }} + {% endfor %} + + +
+ + + +{% endblock %} diff --git a/recipes/templates/add-version.html b/recipes/templates/add-version.html new file mode 100644 index 0000000..e67d86b --- /dev/null +++ b/recipes/templates/add-version.html @@ -0,0 +1,40 @@ +{% extends "base_main.html" %} +{% block title %}{{ recipe.title }}{% endblock %} +{% block main %} +
+ {%csrf_token %} + + {{ version_form.as_table }} +
+ {{ ingredients_formset.management_form }} + {% for ingredient_form in ingredients_formset %} + {{ ingredient_form.as_div }} + {% endfor %} + + +
+ + + +{% endblock %} diff --git a/recipes/templates/edit-recipe.html b/recipes/templates/edit-recipe.html new file mode 100644 index 0000000..09bc18e --- /dev/null +++ b/recipes/templates/edit-recipe.html @@ -0,0 +1,10 @@ +{% extends "base_main.html" %} +{% block title %}{{ recipe.title }}{% endblock %} +{% block main %} +
+ {%csrf_token %} + {{ form.as_div }} + +
+ +{% endblock %} diff --git a/recipes/templates/edit-version.html b/recipes/templates/edit-version.html new file mode 100644 index 0000000..e3fa642 --- /dev/null +++ b/recipes/templates/edit-version.html @@ -0,0 +1,40 @@ +{% extends "base_main.html" %} +{% block title %}{{ recipe.title }}{% endblock %} +{% block main %} +
+ {%csrf_token %} + + {{ version_form.as_table }} +
+ {{ ingredients_formset.management_form }} + {% for ingredient_form in ingredients_formset %} + {{ ingredient_form.as_div }} + {% endfor %} + + +
+ + + +{% endblock %} diff --git a/recipes/templates/recipe.html b/recipes/templates/recipe.html new file mode 100644 index 0000000..08d20d9 --- /dev/null +++ b/recipes/templates/recipe.html @@ -0,0 +1,12 @@ +{% extends "base_main.html" %} +{% block title %}{{ recipe.title }}{% endblock %} +{% block main %} +

{{ recipe.title }}

+

Edit recipe name

+

Add version

+ +{% endblock %} diff --git a/recipes/templates/recipes.html b/recipes/templates/recipes.html new file mode 100644 index 0000000..faee634 --- /dev/null +++ b/recipes/templates/recipes.html @@ -0,0 +1,11 @@ +{% extends "base_main.html" %} +{% block title %}Recipes{% endblock %} +{% block main %} +

Recipes

+

Add recipe

+ +{% endblock %} diff --git a/recipes/templates/version.html b/recipes/templates/version.html new file mode 100644 index 0000000..00ad0ff --- /dev/null +++ b/recipes/templates/version.html @@ -0,0 +1,17 @@ +{% extends "base_main.html" %} +{% block title %}{{ recipe.title }}{% endblock %} +{% block main %} +

{{ version.recipe.title }}{% if has_multiple_versions %} ({{ version.label }}){% endif %}

+{% if has_multiple_versions %} +

Show all versions

+{% endif %} +

Edit recipe name

+

Add version

+

Edit Version

+
    + {% for i in ingredients %} +
  • {{ i.text }}
  • + {% endfor %} +
+

{{ version.body }}

+{% endblock %} From abbba03debb9f752602fd523b27c56677503f2f2 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 11 Mar 2023 19:18:24 +0100 Subject: [PATCH 08/20] Add views --- recipes/views.py | 149 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) diff --git a/recipes/views.py b/recipes/views.py index 91ea44a..032dd20 100644 --- a/recipes/views.py +++ b/recipes/views.py @@ -1,3 +1,148 @@ -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404, redirect +from .models import Recipe, Version, Ingredient +from .forms import RecipeForm, VersionForm, IngredientFormSet +from django.contrib.auth.decorators import login_required +from django.urls import reverse +from django.http.response import HttpResponseRedirect +from django.conf import settings -# Create your views here. +RECIPE_FORM_PREFIX = 'recipe' +VERSION_FORM_PREFIX = 'version' +INGREDIENTS_FORMSET_PREFIX = 'ingredient' + +def get_name_of_user(user): + return user.first_name if user.first_name else user.username + +@login_required +def recipes(request): + recipes = Recipe.objects.all() + return render(request, 'recipes.html', context={'recipes': recipes}) + +def version(request, slug_recipe, slug_version): + recipe = get_object_or_404(Recipe, slug=slug_recipe) + has_multiple_versions = recipe.versions.all().count() > 1 # type: ignore + version = get_object_or_404(Version, recipe=recipe, slug=slug_version) + ingredients = version.ingredients.all() # type: ignore + + return render(request, 'version.html', context={'recipe': recipe, 'has_multiple_versions': has_multiple_versions, 'version': version, 'ingredients': ingredients}) + +@login_required +def recipe(request, slug): + recipe = get_object_or_404(Recipe, slug=slug) + versions = recipe.versions.all() # type: ignore + + if (1 == versions.count()): + return HttpResponseRedirect(reverse('version', kwargs={'slug_recipe': slug, 'slug_version': versions.get().slug})) + else: + return render(request, 'recipe.html', context={'recipe': recipe, 'versions': versions}) + +def create_version(request, recipe: Recipe, version_form: VersionForm) -> Version: + version = version_form.save(commit=False) + version.user = request.user + version.recipe = recipe + version.save() + return version + +def save_ingredients(version: Version, ingredients_formset: IngredientFormSet): # type: ignore + for ingredient in ingredients_formset.save(commit=False): + ingredient.version = version + ingredient.save() + +@login_required +def add_recipe(request): + if request.method == 'POST': + recipe_form = RecipeForm(request.POST, prefix=RECIPE_FORM_PREFIX) + version_form = VersionForm(request.POST, prefix=VERSION_FORM_PREFIX, author_placeholder=get_name_of_user(request.user)) + ingredients_formset = IngredientFormSet(request.POST, queryset=Ingredient.objects.none(), prefix=INGREDIENTS_FORMSET_PREFIX) + + if recipe_form.is_valid() and version_form.is_valid() and ingredients_formset.is_valid(): + recipe = recipe_form.save(commit=True) + version = create_version(request, recipe, version_form) + save_ingredients(version, ingredients_formset) + + return HttpResponseRedirect(reverse('recipe', kwargs={'slug': recipe.slug})) + else: + recipe_form = RecipeForm(prefix=RECIPE_FORM_PREFIX) + version_form = VersionForm(prefix=VERSION_FORM_PREFIX, author_placeholder=get_name_of_user(request.user)) + ingredients_formset = IngredientFormSet(queryset=Ingredient.objects.none(), prefix=INGREDIENTS_FORMSET_PREFIX) + + return render(request, 'add-recipe.html', {'recipe_form': recipe_form, 'version_form': version_form, 'ingredients_formset': ingredients_formset}) + +@login_required +def edit_recipe(request, slug): + recipe = get_object_or_404(Recipe, slug=slug) + + # It is assumed every recipe has at least one version + if not request.user.is_superuser: + users = set() + + for version in recipe.versions.all(): # type: ignore + users.add(version.user) + + if len(users) > 1 or (len(users) == 1 and next(iter(users)) != request.user): + return redirect(f"/accounts/login/?next={request.path}") + + if request.method == 'POST': + form = RecipeForm(request.POST, instance=recipe, prefix=RECIPE_FORM_PREFIX) + if form.is_valid(): + if form.has_changed(): + form.save() + return HttpResponseRedirect(reverse('recipe', kwargs={'slug': recipe.slug})) + else: + form = RecipeForm(instance=recipe, prefix=RECIPE_FORM_PREFIX) + + return render(request, 'edit-recipe.html', {'form': form}) + +@login_required +def add_version(request, slug): + recipe = get_object_or_404(Recipe, slug=slug) + if (recipe.versions.all().count() > 0): # type: ignore + version_initial = {'label': '', 'slug': ''} + else: + version_initial = {} + + if request.method == 'POST': + version_form = VersionForm(request.POST, prefix=VERSION_FORM_PREFIX, initial=version_initial, author_placeholder=get_name_of_user(request.user)) + ingredients_formset = IngredientFormSet(request.POST, queryset=Ingredient.objects.none(), prefix=INGREDIENTS_FORMSET_PREFIX) + version_form.recipe_id = recipe.id # type: ignore + + if version_form.is_valid() and ingredients_formset.is_valid(): + version = create_version(request, recipe, version_form) + save_ingredients(version, ingredients_formset) + + return HttpResponseRedirect(reverse('version', kwargs={'slug_recipe': version.recipe.slug, 'slug_version': version.slug})) + + else: + version_form = VersionForm(prefix=VERSION_FORM_PREFIX, initial=version_initial, author_placeholder=get_name_of_user(request.user)) + ingredients_formset = IngredientFormSet(queryset=Ingredient.objects.none(), prefix=INGREDIENTS_FORMSET_PREFIX) + + return render(request, 'add-version.html', {'version_form': version_form, 'ingredients_formset': ingredients_formset}) + +@login_required +def edit_version(request, slug_recipe, slug_version): + recipe = get_object_or_404(Recipe, slug=slug_recipe) + version = get_object_or_404(Version, recipe=recipe, slug=slug_version) + + if version.user != request.user and not request.user.is_superuser: + return redirect(f"/accounts/login/?next={request.path}") + + if request.method == 'POST': + version_form = VersionForm(request.POST, prefix=VERSION_FORM_PREFIX, instance=version, author_placeholder=get_name_of_user(request.user)) + ingredients_formset = IngredientFormSet(request.POST, queryset=version.ingredients.all(), prefix=INGREDIENTS_FORMSET_PREFIX) # type: ignore + version_form.recipe_id = recipe.id # type: ignore + + if version_form.is_valid() and ingredients_formset.is_valid(): + if version_form.has_changed(): + version = version_form.save() + + if ingredients_formset.has_changed(): + for ingredient in ingredients_formset.save(commit=False): + ingredient.version = version + ingredient.save() + + return HttpResponseRedirect(reverse('version', kwargs={'slug_recipe': version.recipe.slug, 'slug_version': version.slug})) + else: + version_form = VersionForm(instance=version, prefix=VERSION_FORM_PREFIX, author_placeholder=get_name_of_user(request.user)) + ingredients_formset = IngredientFormSet(queryset=version.ingredients.all(), prefix=INGREDIENTS_FORMSET_PREFIX) # type: ignore + + return render(request, 'edit-version.html', {'version_form': version_form, 'ingredients_formset': ingredients_formset}) From 2f4ed102d76a3de64e987e428d8f89cb68de5dea Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 11 Mar 2023 19:19:47 +0100 Subject: [PATCH 09/20] Add url patterns --- recipes/urls.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 recipes/urls.py diff --git a/recipes/urls.py b/recipes/urls.py new file mode 100644 index 0000000..5c7a33f --- /dev/null +++ b/recipes/urls.py @@ -0,0 +1,12 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.recipes, name='recipes'), + path('add-recipe/', views.add_recipe, name='add-recipe'), + path('/add-version/', views.add_version, name='add-version'), + path('/edit-recipe/', views.edit_recipe, name='edit-recipe'), + path('//edit-version/', views.edit_version, name='edit-version'), + path('//', views.version, name='version'), + path('/', views.recipe, name='recipe'), +] From 1d1a0653e5667f597158efdaec096b163d4ceb7f Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sun, 19 Mar 2023 16:00:38 +0100 Subject: [PATCH 10/20] Add license header to source files --- recipes/admin.py | 19 +++++++++++++++++++ recipes/apps.py | 19 +++++++++++++++++++ recipes/forms.py | 19 +++++++++++++++++++ recipes/models.py | 19 +++++++++++++++++++ recipes/templates/add-recipe.html | 18 ++++++++++++++++++ recipes/templates/add-version.html | 18 ++++++++++++++++++ recipes/templates/edit-recipe.html | 18 ++++++++++++++++++ recipes/templates/edit-version.html | 20 +++++++++++++++++++- recipes/templates/recipe.html | 18 ++++++++++++++++++ recipes/templates/recipes.html | 18 ++++++++++++++++++ recipes/templates/version.html | 18 ++++++++++++++++++ recipes/tests.py | 19 +++++++++++++++++++ recipes/urls.py | 19 +++++++++++++++++++ recipes/views.py | 19 +++++++++++++++++++ 14 files changed, 260 insertions(+), 1 deletion(-) diff --git a/recipes/admin.py b/recipes/admin.py index 1542b98..7ffb902 100644 --- a/recipes/admin.py +++ b/recipes/admin.py @@ -1,3 +1,22 @@ +""" +Barn Web App - A collection of web-apps for my family's personal use, +including a recipe database. +Copyright © 2023 Benjamin Stadlbauer + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +General Public License for more details. + +This program comes with a copy of the GNU Affero General Public License +file at the root of this project. +""" + from django.contrib import admin from .models import Recipe, Version, Ingredient diff --git a/recipes/apps.py b/recipes/apps.py index 1d53980..0ed261f 100644 --- a/recipes/apps.py +++ b/recipes/apps.py @@ -1,3 +1,22 @@ +""" +Barn Web App - A collection of web-apps for my family's personal use, +including a recipe database. +Copyright © 2023 Benjamin Stadlbauer + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +General Public License for more details. + +This program comes with a copy of the GNU Affero General Public License +file at the root of this project. +""" + from django.apps import AppConfig diff --git a/recipes/forms.py b/recipes/forms.py index f02cf4d..e410308 100644 --- a/recipes/forms.py +++ b/recipes/forms.py @@ -1,3 +1,22 @@ +""" +Barn Web App - A collection of web-apps for my family's personal use, +including a recipe database. +Copyright © 2023 Benjamin Stadlbauer + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +General Public License for more details. + +This program comes with a copy of the GNU Affero General Public License +file at the root of this project. +""" + from django.forms import ModelForm, ValidationError, modelformset_factory, BooleanField from .models import Recipe, Version, Ingredient diff --git a/recipes/models.py b/recipes/models.py index 80a66ad..bb9728f 100644 --- a/recipes/models.py +++ b/recipes/models.py @@ -1,3 +1,22 @@ +""" +Barn Web App - A collection of web-apps for my family's personal use, +including a recipe database. +Copyright © 2023 Benjamin Stadlbauer + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +General Public License for more details. + +This program comes with a copy of the GNU Affero General Public License +file at the root of this project. +""" + from django.db import models from django.contrib.auth.models import User from django.urls import reverse diff --git a/recipes/templates/add-recipe.html b/recipes/templates/add-recipe.html index bd8968c..f696794 100644 --- a/recipes/templates/add-recipe.html +++ b/recipes/templates/add-recipe.html @@ -1,4 +1,22 @@ {% extends "base_main.html" %} +{% comment %} + Barn Web App - A collection of web-apps for my family's personal use, + including a recipe database. + Copyright © 2023 Benjamin Stadlbauer + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero + General Public License for more details. + + This program comes with a copy of the GNU Affero General Public License + file at the root of this project. +{% endcomment %} {% block title %}{{ recipe.title }}{% endblock %} {% block main %}
diff --git a/recipes/templates/add-version.html b/recipes/templates/add-version.html index e67d86b..fb403db 100644 --- a/recipes/templates/add-version.html +++ b/recipes/templates/add-version.html @@ -1,4 +1,22 @@ {% extends "base_main.html" %} +{% comment %} + Barn Web App - A collection of web-apps for my family's personal use, + including a recipe database. + Copyright © 2023 Benjamin Stadlbauer + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero + General Public License for more details. + + This program comes with a copy of the GNU Affero General Public License + file at the root of this project. +{% endcomment %} {% block title %}{{ recipe.title }}{% endblock %} {% block main %} diff --git a/recipes/templates/edit-recipe.html b/recipes/templates/edit-recipe.html index 09bc18e..32ce3c8 100644 --- a/recipes/templates/edit-recipe.html +++ b/recipes/templates/edit-recipe.html @@ -1,4 +1,22 @@ {% extends "base_main.html" %} +{% comment %} + Barn Web App - A collection of web-apps for my family's personal use, + including a recipe database. + Copyright © 2023 Benjamin Stadlbauer + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero + General Public License for more details. + + This program comes with a copy of the GNU Affero General Public License + file at the root of this project. +{% endcomment %} {% block title %}{{ recipe.title }}{% endblock %} {% block main %} diff --git a/recipes/templates/edit-version.html b/recipes/templates/edit-version.html index e3fa642..0659431 100644 --- a/recipes/templates/edit-version.html +++ b/recipes/templates/edit-version.html @@ -1,7 +1,25 @@ {% extends "base_main.html" %} +{% comment %} + Barn Web App - A collection of web-apps for my family's personal use, + including a recipe database. + Copyright © 2023 Benjamin Stadlbauer + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero + General Public License for more details. + + This program comes with a copy of the GNU Affero General Public License + file at the root of this project. +{% endcomment %} {% block title %}{{ recipe.title }}{% endblock %} {% block main %} - + {# TODO refactor with add-version.html#} {%csrf_token %} {{ version_form.as_table }} diff --git a/recipes/templates/recipe.html b/recipes/templates/recipe.html index 08d20d9..29f2cc0 100644 --- a/recipes/templates/recipe.html +++ b/recipes/templates/recipe.html @@ -1,4 +1,22 @@ {% extends "base_main.html" %} +{% comment %} + Barn Web App - A collection of web-apps for my family's personal use, + including a recipe database. + Copyright © 2023 Benjamin Stadlbauer + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero + General Public License for more details. + + This program comes with a copy of the GNU Affero General Public License + file at the root of this project. +{% endcomment %} {% block title %}{{ recipe.title }}{% endblock %} {% block main %}

{{ recipe.title }}

diff --git a/recipes/templates/recipes.html b/recipes/templates/recipes.html index faee634..67d6ab0 100644 --- a/recipes/templates/recipes.html +++ b/recipes/templates/recipes.html @@ -1,4 +1,22 @@ {% extends "base_main.html" %} +{% comment %} + Barn Web App - A collection of web-apps for my family's personal use, + including a recipe database. + Copyright © 2023 Benjamin Stadlbauer + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero + General Public License for more details. + + This program comes with a copy of the GNU Affero General Public License + file at the root of this project. +{% endcomment %} {% block title %}Recipes{% endblock %} {% block main %}

Recipes

diff --git a/recipes/templates/version.html b/recipes/templates/version.html index 00ad0ff..bac7ea6 100644 --- a/recipes/templates/version.html +++ b/recipes/templates/version.html @@ -1,4 +1,22 @@ {% extends "base_main.html" %} +{% comment %} + Barn Web App - A collection of web-apps for my family's personal use, + including a recipe database. + Copyright © 2023 Benjamin Stadlbauer + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero + General Public License for more details. + + This program comes with a copy of the GNU Affero General Public License + file at the root of this project. +{% endcomment %} {% block title %}{{ recipe.title }}{% endblock %} {% block main %}

{{ version.recipe.title }}{% if has_multiple_versions %} ({{ version.label }}){% endif %}

diff --git a/recipes/tests.py b/recipes/tests.py index 7ce503c..055fc05 100644 --- a/recipes/tests.py +++ b/recipes/tests.py @@ -1,3 +1,22 @@ +""" +Barn Web App - A collection of web-apps for my family's personal use, +including a recipe database. +Copyright © 2023 Benjamin Stadlbauer + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +General Public License for more details. + +This program comes with a copy of the GNU Affero General Public License +file at the root of this project. +""" + from django.test import TestCase # Create your tests here. diff --git a/recipes/urls.py b/recipes/urls.py index 5c7a33f..3561232 100644 --- a/recipes/urls.py +++ b/recipes/urls.py @@ -1,3 +1,22 @@ +""" +Barn Web App - A collection of web-apps for my family's personal use, +including a recipe database. +Copyright © 2023 Benjamin Stadlbauer + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +General Public License for more details. + +This program comes with a copy of the GNU Affero General Public License +file at the root of this project. +""" + from django.urls import path from . import views diff --git a/recipes/views.py b/recipes/views.py index 032dd20..d7eb098 100644 --- a/recipes/views.py +++ b/recipes/views.py @@ -1,3 +1,22 @@ +""" +Barn Web App - A collection of web-apps for my family's personal use, +including a recipe database. +Copyright © 2023 Benjamin Stadlbauer + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +General Public License for more details. + +This program comes with a copy of the GNU Affero General Public License +file at the root of this project. +""" + from django.shortcuts import render, get_object_or_404, redirect from .models import Recipe, Version, Ingredient from .forms import RecipeForm, VersionForm, IngredientFormSet From c5b3e83f6f764fa636a5cc981eca0ce8c0364711 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sun, 19 Mar 2023 18:28:29 +0100 Subject: [PATCH 11/20] Refactor forms --- recipes/templates/add-version.html | 58 ------------------- recipes/templates/edit-version.html | 58 ------------------- .../{add-recipe.html => recipe-form.html} | 12 ++-- recipes/views.py | 6 +- 4 files changed, 9 insertions(+), 125 deletions(-) delete mode 100644 recipes/templates/add-version.html delete mode 100644 recipes/templates/edit-version.html rename recipes/templates/{add-recipe.html => recipe-form.html} (92%) diff --git a/recipes/templates/add-version.html b/recipes/templates/add-version.html deleted file mode 100644 index fb403db..0000000 --- a/recipes/templates/add-version.html +++ /dev/null @@ -1,58 +0,0 @@ -{% extends "base_main.html" %} -{% comment %} - Barn Web App - A collection of web-apps for my family's personal use, - including a recipe database. - Copyright © 2023 Benjamin Stadlbauer - - This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or (at - your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero - General Public License for more details. - - This program comes with a copy of the GNU Affero General Public License - file at the root of this project. -{% endcomment %} -{% block title %}{{ recipe.title }}{% endblock %} -{% block main %} - - {%csrf_token %} -
- {{ version_form.as_table }} -
- {{ ingredients_formset.management_form }} - {% for ingredient_form in ingredients_formset %} - {{ ingredient_form.as_div }} - {% endfor %} - - -
- - - -{% endblock %} diff --git a/recipes/templates/edit-version.html b/recipes/templates/edit-version.html deleted file mode 100644 index 0659431..0000000 --- a/recipes/templates/edit-version.html +++ /dev/null @@ -1,58 +0,0 @@ -{% extends "base_main.html" %} -{% comment %} - Barn Web App - A collection of web-apps for my family's personal use, - including a recipe database. - Copyright © 2023 Benjamin Stadlbauer - - This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or (at - your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero - General Public License for more details. - - This program comes with a copy of the GNU Affero General Public License - file at the root of this project. -{% endcomment %} -{% block title %}{{ recipe.title }}{% endblock %} -{% block main %} -
{# TODO refactor with add-version.html#} - {%csrf_token %} - - {{ version_form.as_table }} -
- {{ ingredients_formset.management_form }} - {% for ingredient_form in ingredients_formset %} - {{ ingredient_form.as_div }} - {% endfor %} - - -
- - - -{% endblock %} diff --git a/recipes/templates/add-recipe.html b/recipes/templates/recipe-form.html similarity index 92% rename from recipes/templates/add-recipe.html rename to recipes/templates/recipe-form.html index f696794..0d3de9f 100644 --- a/recipes/templates/add-recipe.html +++ b/recipes/templates/recipe-form.html @@ -19,12 +19,12 @@ {% endcomment %} {% block title %}{{ recipe.title }}{% endblock %} {% block main %} -
+ {%csrf_token %} - {{ recipe_form.as_div }} - - {{ version_form.as_table }} -
+ {% if recipe_form %} + {{ recipe_form.as_div }} + {% endif %} + {{ version_form.as_div }} {{ ingredients_formset.management_form }} {% for ingredient_form in ingredients_formset %} {{ ingredient_form.as_div }} @@ -36,7 +36,7 @@