added recipe images
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -61,6 +61,8 @@ target/
|
|||||||
|
|
||||||
venv/
|
venv/
|
||||||
|
|
||||||
|
mediafiles/
|
||||||
|
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
|
|
||||||
\.idea/workspace\.xml
|
\.idea/workspace\.xml
|
||||||
|
@ -33,7 +33,7 @@ class ExternalRecipeForm(forms.ModelForm):
|
|||||||
class InternalRecipeForm(forms.ModelForm):
|
class InternalRecipeForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Recipe
|
model = Recipe
|
||||||
fields = ('name', 'instructions', 'time', 'keywords')
|
fields = ('name', 'instructions', 'image', 'time', 'keywords')
|
||||||
|
|
||||||
labels = {
|
labels = {
|
||||||
'name': _('Name'),
|
'name': _('Name'),
|
||||||
|
18
cookbook/migrations/0006_recipe_image.py
Normal file
18
cookbook/migrations/0006_recipe_image.py
Normal file
@ -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/'),
|
||||||
|
),
|
||||||
|
]
|
@ -1,4 +1,8 @@
|
|||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.core.files import File
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
@ -53,6 +57,7 @@ class Keyword(models.Model):
|
|||||||
class Recipe(models.Model):
|
class Recipe(models.Model):
|
||||||
name = models.CharField(max_length=128)
|
name = models.CharField(max_length=128)
|
||||||
instructions = models.TextField(blank=True)
|
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)
|
storage = models.ForeignKey(Storage, on_delete=models.PROTECT, blank=True, null=True)
|
||||||
file_uid = models.CharField(max_length=256, default="")
|
file_uid = models.CharField(max_length=256, default="")
|
||||||
file_path = models.CharField(max_length=512, default="")
|
file_path = models.CharField(max_length=512, default="")
|
||||||
@ -67,6 +72,14 @@ class Recipe(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
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
|
@property
|
||||||
def all_tags(self):
|
def all_tags(self):
|
||||||
return ' '.join([(x.icon + x.name) for x in self.keywords.all()])
|
return ' '.join([(x.icon + x.name) for x in self.keywords.all()])
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<h3>{% trans 'Edit Recipe' %}</h3>
|
<h3>{% trans 'Edit Recipe' %}</h3>
|
||||||
|
|
||||||
<form action="." method="post">
|
<form action="." method="post" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
{% for field in form %}
|
{% for field in form %}
|
||||||
|
@ -45,8 +45,9 @@
|
|||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if ingredients %}
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
{% if ingredients %}
|
||||||
<div class="col col-md-6">
|
<div class="col col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -89,7 +90,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% if recipe.image %}
|
||||||
|
<div class="col col-md-6">
|
||||||
|
<img class="img img-fluid rounded" src="{{ recipe.image.url }}">
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% if recipe.ingredients or recipe.image %}
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -40,13 +40,18 @@ def internal_recipe_update(request, pk):
|
|||||||
recipe_instance = get_object_or_404(Recipe, pk=pk)
|
recipe_instance = get_object_or_404(Recipe, pk=pk)
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = InternalRecipeForm(request.POST)
|
form = InternalRecipeForm(request.POST, request.FILES)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
recipe = recipe_instance
|
recipe = recipe_instance
|
||||||
recipe.name = form.cleaned_data['name']
|
recipe.name = form.cleaned_data['name']
|
||||||
recipe.instructions = form.cleaned_data['instructions']
|
recipe.instructions = form.cleaned_data['instructions']
|
||||||
recipe.time = form.cleaned_data['time']
|
recipe.time = form.cleaned_data['time']
|
||||||
|
|
||||||
|
if form.cleaned_data['image']:
|
||||||
|
recipe.image = form.cleaned_data['image']
|
||||||
|
else:
|
||||||
|
recipe.image = None
|
||||||
|
|
||||||
recipe.save()
|
recipe.save()
|
||||||
|
|
||||||
form_ingredients = json.loads(form.data['ingredients'])
|
form_ingredients = json.loads(form.data['ingredients'])
|
||||||
|
@ -52,6 +52,7 @@ INSTALLED_APPS = [
|
|||||||
'crispy_forms',
|
'crispy_forms',
|
||||||
'emoji_picker',
|
'emoji_picker',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
|
'django_cleanup.apps.CleanupConfig',
|
||||||
'cookbook.apps.CookbookConfig',
|
'cookbook.apps.CookbookConfig',
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ TEMPLATES = [
|
|||||||
'django.template.context_processors.request',
|
'django.template.context_processors.request',
|
||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
'django.contrib.messages.context_processors.messages',
|
'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/
|
# https://docs.djangoproject.com/en/2.0/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
|
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
|
||||||
|
|
||||||
|
MEDIA_URL = '/media/'
|
||||||
|
MEDIA_ROOT = os.path.join(BASE_DIR, "mediafiles")
|
||||||
|
@ -13,7 +13,8 @@ Including another URLconf
|
|||||||
1. Import the include() function: from django.urls import include, path
|
1. Import the include() function: from django.urls import include, path
|
||||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
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.urls import include, path
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
@ -22,3 +23,6 @@ urlpatterns = [
|
|||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('accounts/', include('django.contrib.auth.urls')),
|
path('accounts/', include('django.contrib.auth.urls')),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
django
|
django
|
||||||
|
Pillow
|
||||||
django-tables2
|
django-tables2
|
||||||
django-filter
|
django-filter
|
||||||
django-crispy-forms
|
django-crispy-forms
|
||||||
djangorestframework
|
djangorestframework
|
||||||
django-autocomplete-light
|
django-autocomplete-light
|
||||||
django-emoji-picker
|
django-emoji-picker
|
||||||
|
django-cleanup
|
||||||
six
|
six
|
||||||
requests
|
requests
|
||||||
markdown
|
markdown
|
||||||
|
Reference in New Issue
Block a user