[장고] Summernote 패키지

소요 시간: 10분

많은 웹 개발자들이 웹 애플리케이션에서 사용자가 텍스트를 입력하고 편집할 수 있는 편리하고 직관적인 에디터를 찾고 있습니다. 이러한 요구에 부응하기 위해 Django 프로젝트에 Summernote 패키지를 추가하는 방법을 알아보겠습니다. 핵심 서비스에 집중할 수 있다.


Summernote란

Summernote는 사용하기 쉬운 위지위그(WYSIWYG) 에디터로, 텍스트 입력 창을 풍부하게 만들어줍니다. 사용자들은 복잡한 마크업이나 HTML 코드를 알 필요 없이 간단하게 텍스트를 입력하고 서식을 적용할 수 있습니다. Summernote는 심플함을 추구하는 위지위그 에디터다. 다음과 같은 장점들이 있다.

위지위그

위지위그 편집기는 개발자가 인터페이스나 문서를 작성하는 동안 실제 출력물이 어떻게 보일지를 미리 확인할 수 있는 편집 도구입니다. "보이는 대로"를 의미하는 위지위그는 스타일을 적용한 결과를 즉시 확인할 수 있는 텍스트 에디터로서의 장점을 가지고 있다.

사용의 용이성

Summernote는 장고에 연동하기 쉽우면서도 높은 완성도를 자랑합니다. 무료로 제공되지만, 거의 모든 종류의 텍스트를 손쉽게 입력할 수 있다.

무료

CKEditor 등 다양한 위지위그 에디터가 있지만, 상업적 이용을 위해서는 매월 일정 금액을 지불해야 하는 경우도 많습니다. 그러나 Summernote는 MIT 라이센스를 채택하여, 상업적인 목적으로도 무료로 이용할 수 있습니다.


구현하기

이 블로그 포스트에서는 Django 프로젝트에 Summernote를 통합하는 과정을 단계별로 안내할 것입니다. 시작하기 전에 몇 가지 준비물이 필요합니다. 아래에 필요한 사항을 간략히 나열해 보았습니다.

준비가 되었다면, 이제 Summernote를 Django 프로젝트에 추가하는 과정에 대해 알아보겠습니다. 함께 따라와 주세요!

환경 설정

먼저 django-summernote 패키지를 설치합니다. pip를 사용하여 다음 명령어를 실행하세요:

$ pip3 install django-summernote

설치가 완료되면, Django 프로젝트의 settings.py 파일을 열고 INSTALLED_APPS에 django_summernote를 추가합니다.

# settings.py
INSTALLED_APPS = [
    # ...생략...,
    'django_summernote',
]

URL 설정

urls.py 파일에 django_summernote의 URL 패턴을 추가합니다. 일반적으로 프로젝트의 최상위 urls.py 파일에 추가합니다.

# urls.py
from django.urls import path, include

urlpatterns = [
    # 생략
    path('summernote/', include('django_summernote.urls')),
]

그리고 settings.py에 미디어 파일이 저장될 경로를 설정한다.

# settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

모델 설정

글을 관리하는 post 앱을 새로 생성합니다.

$ python3 manage.py startapp posts

그 다음 models.py를 열고 간단한 post 모델을 정의합니다.

# posts/models.py
from django.db import models

# Create your models here.
class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()

    def __str__(self):
        return f'{self.title}'

어드민 설정

admin.py 파일에서 모델을 어드민 사이트에 등록할 때 SummernoteModelAdmin을 사용합니다.

from django.contrib import admin
from .models import Post
from django_summernote.admin import SummernoteModelAdmin

class PostAdmin(SummernoteModelAdmin):
    pass

admin.site.register(Post, PostAdmin)

추가 설정 (선택사항)

추가적으로, settings.py 파일에서 SUMMERNOTE_CONFIG 변수를 사용하여 Summernote의 다양한 설정을 조정할 수 있습니다.

SUMMERNOTE_CONFIG = {
    'summernote': {
        'width': '100%',
        'height': '400px',
    },
    'toolbar': [
        ['style', ['style']],
        ['font', ['bold', 'italic', 'underline', 'clear']],
        ['fontname', ['fontname']],
        ['color', ['color']],
        ['para', ['ul', 'ol', 'paragraph']],
        ['height', ['height']],
        ['table', ['table']],
        ['insert', ['link', 'picture', 'video']],
        ['view', ['fullscreen', 'codeview', 'help']],
    ],
}

이로써 Django 프로젝트에 Summernote를 통합하는 기본적인 설정이 완료되었습니다. 이를 통해 관리자 페이지에서 WYSIWYG 편집기를 사용할 수 있으며, 다양한 콘텐츠를 손쉽게 편집할 수 있습니다. 


포스트 에디터 페이지 만들기

이번에는 관리자 페이지가 아닌 에디터 페이지를 직접 만들어보겠습니다.

섬머노트 위젯 폼 생성

posts 앱에 forms.py 파일을 생성하고 Summernote를 이용하여 content 필드를 등록합니다.

# forms.py
from django import forms
from .models import Post

from django_summernote.widgets import SummernoteWidget

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content']
        widgets = {
            'content': SummernoteWidget(),
        }

View에서 Form을 불러와서 사용합니다.

from .forms import PostForm
from django.views.generic.edit import FormView

class PostFormView(FormView):
    template_name = 'post_add.html'
    form_class = PostForm
    success_url = '/thanks/'

    def form_valid(self, form):
        # This method is called when valid form data has been POSTed.
        # It should return an HttpResponse.
        return super().form_valid(form)

url과 view를 연결(mapping)한다.

# posts/urls.py
app_name = 'posts' # url 네임 스페이스

urlpatterns = [
    path('add/', views.PostFormView.as_view()),        
]

에디터 페이지 템플릿 제작

HTML 템플릿에 form 태그를 작성한다.

<form action="" method="POST">
    {% csrf_token %}
    <table>
        {{form.as_table}}
    </table>
    <input type="submit" value="등록하기">
</form>

테스트 서버를 실행한 후 해당 URL로 이동하면 브라우저에서 텍스트 에디터를 볼 수 있습니다.


기폰 폰트 사이즈 변경하기

에디터의 기본 속성을 변경해보겠습니다.

1. static/css 폴더 안에 새로운 CSS 파일을 생성하고, 다른 스타일 설정과 구분되도록 custom-summernote.css라는 이름으로 저장합니다. 섬머노트 에디터의 스타일은 이 파일에서 변경할 수 있습니다.

섬머노트 에디터의 스타일은 이 파일에서 변경한다.

2. 아래 스타일을 입력합니다.

.note-editable {
    font-size: 16px;
}

3. settings.py에서 CSS의 경로를 입력합니다.

# settings.py
SUMMERNOTE_CONFIG = {
    'iframe': True,
    'summernote': {
        # Cange editor size
        'width': '100%',
        ...

        # Customize toolbar buttons
        'toolbar': [
            ['undo', ['undo',]],
            ...
        ],
    },
    # 이 부분을 추가한다.
    'css': ('/static/css/custom_summernote.css',), 
}

기타 옵션으로 폰트 사이즈 변경 및 커스텀이 가능합니다. 자세한 내용은 여기를 참고하세요.


텍스트 도구 맞춤 설정하기

텍스트 에디터에는 폰트 크기 변경, 이미지 삽입 등 다양한 도구들이 포함되어 있습니다. 일부 도구들은 기본적으로 제공되지만, 불필요한 도구들도 포함되어 있을 수 있습니다. Summernote 에디터를 사용하면 도구 상자를 원하는 대로 커스터마이즈할 수 있습니다. 사용하지 않는 도구를 숨기고 편집 환경을 더 깔끔하게 만들어야 할 때도 있습니다. 사용자 경험에 맞춰 도구들을 커스텀해봅시다.

이는 간단합니다. 값을 입력하기만 하면 됩니다.

이를 위해 settings.py 파일에 다음과 같은 코드를 입력합니다.

SUMMERNOTE_CONFIG = {
'iframe': True,
'summernote': {
    # Cange editor size
    'width': '100%',
    'lang': 'ko-KR',

    # Customize toolbar buttons
    'toolbar': [
        ['style', ['style']],
        ['style', ['bold', 'italic', 'underline', 'clear']],
        ['para', ['ul', 'ol', 'paragraph']],
        ['insert', ['link', 'picture']],
        ['table', ['table']],
    ],
},
}

이 코드를 통해 에디터의 크기를 조절하고 언어를 설정할 수 있습니다. 또한, 사용하지 않는 도구를 숨기거나 새로운 도구를 추가하여 도구 상자를 원하는 대로 조정할 수 있습니다. 원하는 도구 버튼을 선택하여 편집 환경을 최적화하세요.

옵션

기타 옵션은 깃허브에 등록된 summernote의 readme를 참고바랍니다.


폰트 사이즈 리스트 바꾸기

1. yoursite/settings.py를 열고 SUMMERNOTE_CONFIG에 폰트 리스트를 추가합니다.

# settings.py
SUMMERNOTE_CONFIG = {
...
'summernote': {
    ....
    # Customize toolbar buttons
    'toolbar': [
        ...
        ['fontsize', ['fontsize']], # Add this line
    ],
    # Add this line too
    'fontSizes': ['12', '16', '20', '24', '36', '48', '64', '82',], 
},
}

그리고 기본 폰트 사이즈를 설정할 수 있다. 자세한 내용은 여기를 참고합니다.


자동으로 썸네일 저장하기

Summernote 에디터의 내용은 CharField 혹은 TextField에 저장됩니다.

# models.py
content = models.TextField()

# forms.py
widgets = {
'content': SummernoteWidget(),
}

Summernote 에디터는 이미지를 별도로 저장하지 않습니다. 썸네일 표기에 대해 고민하던 중, 구글 Blogger가 첫 번째 이미지를 썸네일로 사용하는 방식을 활용하기로 했습니다.

content 필드에 HTML 코드가 저장되기 때문에, 이를 파싱하여 이미지를 쉽게 가져올 수 있습니다. 먼저, 파싱을 도와주는 라이브러리를 설치합니다:

$ pip install beautifulsoup4

썸네일을 작게 줄여 저장하는 대신, 이번 글에서는 원리만 설명하므로 이미지 주소만 따로 저장합니다.

먼저, 이미지 주소를 저장할 CharField를 모델에 추가합니다:

thumbnaiil_url = models.CharField(max_length=100, null=True)

이미지를 등록하지 않는 글도 있을 수 있으므로 null 값을 허용합니다.

이제 forms.py나 views.py를 열어 form_valid 메서드를 오버라이딩합니다:

def form_valid(self, form):
obj = form.save(commit=False)
content = form.cleaned_data['content']
imgs = BeautifulSoup(content, "html.parser").findAll("img")
if len(imgs) > 0:
    obj.thumbnail_url = imgs[0]['src']
obj.save()
return HttpResponseRedirect(reverse("posts:detail", kwargs={"category":obj.category, "slug":obj.slug}))

이렇게 하면 Summernote 에디터에서 첫 번째 이미지를 썸네일로 자동 저장할 수 있습니다.


결론

이번 가이드에서는 Django 프로젝트에 Summernote 패키지를 통합하고, 이를 활용하여 다양한 기능을 구현하는 방법을 다루었습니다.

Summernote 설치 및 설정:

먼저, pip install django-summernote 명령어로 Summernote 패키지를 설치했습니다. 그런 다음, settings.py 파일에 django_summernote를 추가하고, urls.py 파일에 Summernote URL 패턴을 등록했습니다. 이후, models.py와 admin.py 파일에서 SummernoteTextField와 SummernoteModelAdmin을 사용하여 Summernote 편집기를 설정했습니다.

Custom CSS 설정:

static/css 폴더에 custom-summernote.css 파일을 생성하고, Summernote 에디터의 스타일을 이 파일에서 변경하도록 설정했습니다.

도구 상자 커스터마이징:

Summernote 에디터의 도구 상자를 원하는 대로 커스터마이즈하는 방법을 설명했습니다. 이를 통해 사용하지 않는 도구를 숨기고, 필요한 도구만 표시하여 편집 환경을 최적화할 수 있었습니다.

자동 썸네일 저장 기능 구현:

BeautifulSoup 라이브러리를 사용하여 Summernote 에디터의 내용에서 첫 번째 이미지를 추출하고, 이를 썸네일로 자동 저장하는 방법을 설명했습니다. 구체적으로는 form_valid 메서드를 오버라이딩하여, 사용자가 작성한 글의 첫 번째 이미지를 썸네일로 저장하는 로직을 구현했습니다.

이를 통해 Django 프로젝트에서 Summernote를 효과적으로 사용하고, 사용자 경험을 향상시킬 수 있는 다양한 방법을 배웠습니다. 각 단계별로 설명한 설정과 코드는 실제 프로젝트에 적용하여 커스터마이즈된 편집기와 자동 썸네일 기능을 구현하는 데 유용할 것입니다.

이전 글 장고 리스트