- Django 3 Web Development Cookbook
- Aidas Bendoraitis Jake Kronika
- 308字
- 2025-04-04 13:15:08
How to do it...
Execute these steps to complete the recipe:
- Modify the Idea model to add a picture field and image version specifications:
# myproject/apps/ideas/models.py
import contextlib
import os
from imagekit.models import ImageSpecField
from pilkit.processors import ResizeToFill
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils.timezone import now as timezone_now
from myproject.apps.core.models import (CreationModificationDateBase, UrlBase)
def upload_to(instance, filename):
now = timezone_now()
base, extension = os.path.splitext(filename)
extension = extension.lower()
return f"ideas/{now:%Y/%m}/{instance.pk}{extension}"
class Idea(CreationModificationDateBase, UrlBase):
# attributes and fields…
picture = models.ImageField(
_("Picture"), upload_to=upload_to
)
picture_social = ImageSpecField(
source="picture",
processors=[ResizeToFill(1024, 512)],
format="JPEG",
options={"quality": 100},
)
picture_large = ImageSpecField(
source="picture",
processors=[ResizeToFill(800, 400)],
format="PNG"
)
picture_thumbnail = ImageSpecField(
source="picture",
processors=[ResizeToFill(728, 250)],
format="PNG"
)
# other fields, properties, and methods…
def delete(self, *args, **kwargs):
from django.core.files.storage import default_storage
if self.picture:
with contextlib.suppress(FileNotFoundError):
default_storage.delete(
self.picture_social.path
)
default_storage.delete(
self.picture_large.path
)
default_storage.delete(
self.picture_thumbnail.path
)
self.picture.delete()
super().delete(*args, **kwargs)
- Create a model form, IdeaForm, for the Idea model in forms.py, just like we did in the previous recipes.
- In the view for adding or changing ideas, make sure to post request.FILES beside request.POST to the form:
# myproject/apps/ideas/views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import (render, redirect, get_object_or_404)
from django.conf import settings
from .forms import IdeaForm
from .models import Idea
@login_required
def add_or_change_idea(request, pk=None):
idea = None
if pk:
idea = get_object_or_404(Idea, pk=pk)
if request.method == "POST":
form = IdeaForm(
request,
data=request.POST,
files=request.FILES,
instance=idea,
)
if form.is_valid():
idea = form.save()
return redirect("ideas:idea_detail", pk=idea.pk)
else:
form = IdeaForm(request, instance=idea)
context = {"idea": idea, "form": form}
return render(request, "ideas/idea_form.html", context)
- In the template, make sure to have encoding type set to "multipart/form-data", as follows:
<form action="{{ request.path }}" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<button type="submit">{% trans "Save" %}</button>
</form>
If you are using django-crispy-form as described in the Creating a form layout with django-crispy-forms recipe, the enctype attribute will be added to the form automatically.