diff --git a/.gitignore b/.gitignore index 91b02003..a6267286 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,8 @@ target/ venv/ +mediafiles/ + *.sqlite3 \.idea/workspace\.xml diff --git a/cookbook/forms.py b/cookbook/forms.py index 88e26abb..e7d0e4e4 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -33,7 +33,7 @@ class ExternalRecipeForm(forms.ModelForm): class InternalRecipeForm(forms.ModelForm): class Meta: model = Recipe - fields = ('name', 'instructions', 'time', 'keywords') + fields = ('name', 'instructions', 'image', 'time', 'keywords') labels = { 'name': _('Name'), diff --git a/cookbook/migrations/0006_recipe_image.py b/cookbook/migrations/0006_recipe_image.py new file mode 100644 index 00000000..10b41e09 --- /dev/null +++ b/cookbook/migrations/0006_recipe_image.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.1 on 2019-12-25 15:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0005_recipebook_recipebookentry'), + ] + + operations = [ + migrations.AddField( + model_name='recipe', + name='image', + field=models.ImageField(blank=True, null=True, upload_to='recipes/'), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index 0e549f43..0504d9dc 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -1,4 +1,8 @@ +from io import BytesIO + +from PIL import Image from django.contrib.auth.models import User +from django.core.files import File from django.db import models @@ -53,6 +57,7 @@ class Keyword(models.Model): class Recipe(models.Model): name = models.CharField(max_length=128) instructions = models.TextField(blank=True) + image = models.ImageField(upload_to='recipes/', blank=True, null=True) storage = models.ForeignKey(Storage, on_delete=models.PROTECT, blank=True, null=True) file_uid = models.CharField(max_length=256, default="") file_path = models.CharField(max_length=512, default="") @@ -67,6 +72,14 @@ class Recipe(models.Model): def __str__(self): return self.name + def save(self, *args, **kwargs): + if self.image: + im = Image.open(self.image) + im_io = BytesIO() + im.save(im_io, 'JPEG', quality=70) + self.image = File(im_io, name=(str(self.pk)+'.jpeg')) + super().save(*args, **kwargs) + @property def all_tags(self): return ' '.join([(x.icon + x.name) for x in self.keywords.all()]) diff --git a/cookbook/templates/forms/edit_internal_recipe.html b/cookbook/templates/forms/edit_internal_recipe.html index 65f4d000..7019fb25 100644 --- a/cookbook/templates/forms/edit_internal_recipe.html +++ b/cookbook/templates/forms/edit_internal_recipe.html @@ -15,7 +15,7 @@

{% trans 'Edit Recipe' %}

-
+ {% csrf_token %} {% for field in form %} diff --git a/cookbook/templates/recipe_view.html b/cookbook/templates/recipe_view.html index ff13a392..afd82acf 100644 --- a/cookbook/templates/recipe_view.html +++ b/cookbook/templates/recipe_view.html @@ -45,8 +45,9 @@
{% endif %} - {% if ingredients %} -
+ +
+ {% if ingredients %}
@@ -89,7 +90,15 @@
-
+ + {% endif %} + {% if recipe.image %} +
+ +
+ {% endif %} +
+ {% if recipe.ingredients or recipe.image %}

{% endif %} diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py index c2cd06cb..3fd6b5fa 100644 --- a/cookbook/views/edit.py +++ b/cookbook/views/edit.py @@ -40,13 +40,18 @@ def internal_recipe_update(request, pk): recipe_instance = get_object_or_404(Recipe, pk=pk) if request.method == "POST": - form = InternalRecipeForm(request.POST) + form = InternalRecipeForm(request.POST, request.FILES) if form.is_valid(): recipe = recipe_instance recipe.name = form.cleaned_data['name'] recipe.instructions = form.cleaned_data['instructions'] recipe.time = form.cleaned_data['time'] + if form.cleaned_data['image']: + recipe.image = form.cleaned_data['image'] + else: + recipe.image = None + recipe.save() form_ingredients = json.loads(form.data['ingredients']) diff --git a/recipes/settings.py b/recipes/settings.py index 5cf981c7..b698948d 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -52,6 +52,7 @@ INSTALLED_APPS = [ 'crispy_forms', 'emoji_picker', 'rest_framework', + 'django_cleanup.apps.CleanupConfig', 'cookbook.apps.CookbookConfig', ] @@ -79,6 +80,7 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + 'django.template.context_processors.media', ], }, }, @@ -139,5 +141,7 @@ LANGUAGES = [ # https://docs.djangoproject.com/en/2.0/howto/static-files/ STATIC_URL = '/static/' - STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") + +MEDIA_URL = '/media/' +MEDIA_ROOT = os.path.join(BASE_DIR, "mediafiles") diff --git a/recipes/urls.py b/recipes/urls.py index 09503d92..50ffd0fe 100644 --- a/recipes/urls.py +++ b/recipes/urls.py @@ -13,7 +13,8 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ -from django.http import HttpResponseRedirect +from django.conf import settings +from django.conf.urls.static import static from django.urls import include, path from django.contrib import admin @@ -22,3 +23,6 @@ urlpatterns = [ path('admin/', admin.site.urls), path('accounts/', include('django.contrib.auth.urls')), ] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/requirements.txt b/requirements.txt index 44e30226..6b957e93 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,12 @@ django +Pillow django-tables2 django-filter django-crispy-forms djangorestframework django-autocomplete-light django-emoji-picker +django-cleanup six requests markdown