과제

📝 Django Todo 프로젝트: 이미지 처리 + Summernote + Bootstrap5 통합 실습 정리

Chansman 2025. 5. 12. 18:15

📝 Django Todo 프로젝트: 이미지 처리 + Summernote + Bootstrap5 통합 실습 정리


✅ 목표 요약

  1. django-summernote를 활용한 rich text 편집 기능 적용
  2. ImageField + Pillow로 이미지 썸네일 자동 생성 로직 구현
  3. django-cleanup으로 이미지 수정/삭제 시 파일 정리 자동화
  4. Bootstrap5 기반 Form UI 개선 및 정리

📦 필요한 라이브러리 설치

poetry add django-summernote pillow django-cleanup

그리고 settings.py에 다음 설정 추가:

INSTALLED_APPS = [
    ...
    'django_summernote',
    'django_cleanup.apps.CleanupConfig',  # ✅ 파일 자동 삭제 처리
]

📌 Summernote 보안 설정 예시:

X_FRAME_OPTIONS = 'SAMEORIGIN'
SUMMERNOTE_CONFIG = {
    'iframe': False,
    'summernote': {
        'disableDragAndDrop': True,
    },
}

🧱 1. Todo 모델 수정하기

from django.db import models
from PIL import Image
from io import BytesIO
from django.core.files.base import ContentFile
from pathlib import Path

class Todo(models.Model):
    ...
    completed_image = models.ImageField(upload_to='todo/images/', null=True, blank=True)
    thumbnail = models.ImageField(upload_to='todo/thumbs/', null=True, blank=True, default='todo/thumbs/default.png')

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

        if self.completed_image:
            image = Image.open(self.completed_image)
            image.thumbnail((300, 300))

            image_path = Path(self.completed_image.name)
            filename_stem = image_path.stem
            file_ext = image_path.suffix
            thumb_name = f'{filename_stem}_thumb{file_ext}'

            temp_thumb = BytesIO()
            image.save(temp_thumb, format=image.format)
            temp_thumb.seek(0)

            self.thumbnail.save(thumb_name, ContentFile(temp_thumb.read()), save=False)
            temp_thumb.close()
            super().save(*args, **kwargs)

🧾 2. TodoForm, TodoUpdateForm 구성

from django import forms
from django_summernote.widgets import SummernoteWidget
from .models import Todo

class TodoForm(forms.ModelForm):
    class Meta:
        model = Todo
        fields = '__all__'
        widgets = {
            'description': SummernoteWidget(),
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'start_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
            'end_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
        }

class TodoUpdateForm(forms.ModelForm):
    class Meta:
        model = Todo
        fields = '__all__'
        widgets = {
            'description': SummernoteWidget(),
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'start_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
            'end_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
            'is_completed': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
            'completed_image': forms.FileInput(attrs={'class': 'form-control'}),
        }

⚙️ 3. cb_views.py 설정

from .forms import TodoForm, TodoUpdateForm

class TodoCreateView(CreateView):
    model = Todo
    form_class = TodoForm

class TodoUpdateView(UpdateView):
    model = Todo
    form_class = TodoUpdateForm

🛠 4. admin.py 설정

from django_summernote.admin import SummernoteModelAdmin

class TodoAdmin(SummernoteModelAdmin):
    summernote_fields = ('description',)
    fieldsets = (
        (None, {'fields': ('title', 'description', 'completed_image', 'thumbnail')}),
    )

🎨 5. 템플릿 수정 (todo_form.html 등)

📄 todo_list.html

{% for todo in todos %}
  <div class="card">
    <img src="{{ todo.thumbnail.url }}" class="card-img-top" alt="썸네일">
    <div class="card-body">
      <h5>{{ todo.title }} {% if todo.is_completed %}<span class="badge bg-success">Completed</span>{% endif %}</h5>
      ...
    </div>
  </div>
{% endfor %}

📄 todo_form.html

<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit" class="btn btn-primary">저장</button>
</form>

📌 todo_create.html, todo_update.html → {% include 'todo_form.html' %} 방식으로 구성하세요.


✅ 최종 체크리스트

  • django-summernote 적용 및 XSS 방지 설정
  • Pillow로 썸네일 자동 생성 로직 구현
  • django-cleanup으로 이미지 정리 자동화
  • Bootstrap5로 템플릿 UI 개선
  • Form 및 Admin 최적화 구성 완료

필요시 미디어 루트 설정, static 경로, default 이미지 등록 위치까지 추가 안내 가능합니다 ✅