장고:썸머노트 설치: 두 판 사이의 차이

학교의 모든 지식. SMwiki
둘러보기로 이동 검색으로 이동
14번째 줄: 14번째 줄:


=django-summernote 모듈로 설치하는 방법=
=django-summernote 모듈로 설치하는 방법=
이 방법보다 부트스트랩 위에 올리는 방법이 더 괜찮다;; 이 방법은 쓰지 말자. 아래 참조.
이 방법보다 부트스트랩 위에 올리는 방법이 더 괜찮다;;(2022.05기준 반응형으로 넣기 어렵다.) 이 방법은 쓰지 말자.
{| class="wikitable"
{| class="wikitable"
|+
|+

2022년 5월 4일 (수) 11:49 판

장고! 웹 프레임워크! 틀:장고

  1. 장고:개요
  2. 장고:웹페이지설계
    1. 장고:앱
    2. 장고:url
    3. 장고:model
      1. 장고:DB
      2. 장고:모델 필드
      3. 장고:모델의 변경
    4. 장고:view
      1. 장고:클래스형 뷰, 제네릭 뷰
      2. 장고:view 각종 기능
    5. 장고:template
    6. 장고:static. 정적파일 사용하기
      1. 장고:CSS 사용하기
      2. 장고:JS 사용하기
      3. 장고:글꼴 사용
      4. 장고:부트스트랩
    7. 장고:media. 미디어 파일 사용하기
  3. 장고:관리자페이지
  4. 장고:settings.py
  5. 장고:기능구현
    1. 장고:회원관리
    2. 장고:유저
    3. 장고:커스텀 유저
    4. 장고:소셜로그인
    5. 장고:입력받기
    6. 장고:저장된 내용 활용하기
    7. 장고:변수 내보내기
    8. 장고:글쓰기
    9. 장고:페이징(페이지나누기)
    10. 장고:답변쓰기(댓글쓰기)
    11. 장고:추천,즐겨찾기
    12. 장고:새글(최신글) 나타내기
    13. 장고:썸머노트 설치
    14. 장고:네비게이션 바 만들기
    15. 장고:검색기능
    16. 장고:카테고리 만들기
    17. 장고:사진 올리기
    18. 장고:파일 업로드
    19. 장고:이메일app 만들기
    20. 장고:매직 그리드
  6. 장고:웹서비스
    1. 장고:Git
    2. 장고:리눅스에 올리기
    3. 장고:우분투에 올리기(nginx 사용)
    4. 장고:도커로 올리기
  7. 장고:팁

개요

WYSIWYG

위징위그. What You See Is What You Get 의 약자이다. 일반적으로 입력을 하면 코드를 사용하여 입력을 해야 사용자가 원하는 크기, 색의 글을 쓸 수 있다. 제대로 된 게시판, 사용자 친화적인 게시판이 되기 위해선 필수적인 기능이다.

네이버 스마트에디터, MediumEditor, 섬머노트 등이 오픈되어있다.


일반적인 textarea에서 표현할 수 있는 방식은 굉장히 적다. 적어도 위키처럼 목차관리를 해준다든가, 링크를 만든다든가 정도는 되야 하지 않을까. 많이 사용되는 에디터인 섬머노트를 장고에 설치해본다.

이미 장고앱으로 개발되어 있어 쉽게 설치가 가능하다.

django-summernote 모듈로 설치하는 방법

이 방법보다 부트스트랩 위에 올리는 방법이 더 괜찮다;;(2022.05기준 반응형으로 넣기 어렵다.) 이 방법은 쓰지 말자.

과정 설명
pip install django-summernote 장고에서 사용하는 썸머노트를 설치.
settings.py의 APP 등록 'django_summernote', 추가
settings.py 설정 이미지 업로드를 위해

MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

추가

settings.py 설정 클릭재킹 방지설정 변경.

'django.middleware.clickjacking.XFrameOptionsMiddleware'라는 미들웨어가 클릭재킹을 방지해주는데, 기본설정이 DENY다.

때문에 아래 옵션을 주어 설정을 변경해준다.
#클릭재킹 방지설정 변경
X_FRAME_OPTIONS = 'SAMEORIGIN'

urls.py 변경 루트 urls.py에 다음의 코드를 추가한다.

path('summernote/', include('django_summernote.urls')),

모델 만들기 기존에 사용하던 모델이 있다면 굳이 만들 필요는 없겠다.
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=10)
    content = models.TextField()

    def __str__(self):
        return self.title
폼 만들기 기존에 사용하던 폼이 있다면 내용을 추가해주면 된다.
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(),}
폼까지 완성했으면 기존의 탬플릿이 잘 작동하나 확인해본다.

혹시나 {{

탬플릿 변경 썸머노트로 입력한 내용은 html코드로 나온다. 탬플릿 필터 |safe 를 사용하여 detail.html의 콘텐츠 부분을 다음과 같이 수정한다.
<div class="card-text" style="white-space: pre-line;">{{ question.content| safe  }}</div>

근데, 이 섬머노트는 반응형이 아니다; 반영할 수 있는 방법이 있을까?


부트스트랩 위에 올리기

썸머노트 공식페이지에 설명되어 있다. https://summernote.org/getting-started/#for-bootstrap-4

역시, 공식사이트가 가장 적절하다.

글쓰기 환경에서만 작동하면 되니, 예시코드를 해석해 create.html 등에 두면 된다.

어려운 사람은 다음을 참고하자. 다음 코드가 <head>태그 안에 들어가게 하고..

    <meta charset="UTF-8">
    <title>Summernote with Bootstrap 4</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/summernote-bs4.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/summernote-bs4.min.js"></script>

다음을 폼 안의 적절한 장소에 기입하면 썸머노트 에디터를 볼 수 있다.(input으로 두면 안되고 textarea로 두어야 되더라;;)

<textarea name="content" id="summernote">
        {{ form.content.value|default_if_none:'' }}</textarea>
        
        
    <script>
      $('#summernote').summernote({
        placeholder: '여기에 내용 입력하세요~',
        tabsize: 2,
        height: 100
      });
    </script>

간단하게 넣을 수 있고, 반응형이다. 다만, 몇몇 tool이 안보인다.(가장 라이트한 형태로 보여진다. 기능이 없는 것은 아닌데, 툴바에 안보일 뿐.)

툴바를 어떻게 구성할지는 https://summernote.org/deep-dive/#initialization-options 에서 안내한다.

툴들을 묶는 이름은 style 등으로 제시하는데, 임의로 둘 수 있다.

영어긴 하지만 끝까지 읽어보면 기능이 정말 많다; 솔직히 좀 놀람;;;

드롭다운 버튼 작동

그런데, 위처럼 작성하면 드롭다운 버튼을 한 번 누르고 난 후에 다시 눌리지가 않는 기현상이 발생한다. 썸머노트의 구조적인 문제라고 하는데[1], 다음의 한 줄을 썸머노트코드 마지막 줄에 추가하자.

$('.dropdown-toggle').dropdown()

재미난 옵션

airMode: true, 편집창 안에 입력하는 게 아니라, 텍스트를 블록선택하면 텍스트를 변경할 수 있게 하는 창이 뜬다.
lang: 'ko-KR', 기본언어는 영어인데, 한글로 설정한다.(안되던데??)
fontNames: ['Arial', 'Arial Black', 'Comic Sans MS', 'Courier New','맑은 고딕','궁서','굴림체','굴림','돋음체','바탕체'],

많은 글씨체를 지원한다. 그냥 위 목록에 추가하면 자동 추가됨.

defaultFontName: '돋음체',

기본 글씨체를 선택할 수 있다.(안되던데??)

maximumImageFileSize: 최대그림 크기. 바이트 단위이다. 크기에 맞춰 단위를 변경해 표시해준다.

스크립트 예시

나는 다음과 같은 형식을 선호한다.

<script>
      $('#summernote').summernote({
        placeholder: '여기에 내용 입력하세요~ 그림파일 용량은 2MB까지입니다~',
        tabsize: 2,
        height: 300, // 에디터 높이
        defaultFontName: '바탕체',
        toolbar: [
  ['style', ['style']],
  ['fontname', ['fontname']],
  ['fontsize', ['fontsize']],
  ['font style', ['bold', 'italic', 'underline','strikethrough', 'clear']],
  ['color', ['forecolor','color']],
  ['para', ['ul', 'ol', 'paragraph']],
  ['table', ['table']],
  ['insert', ['link', 'picture', 'video']],
  ['view', ['fullscreen', 'codeview', 'help']],
],
    defaultFontName:'바탕',
    fontNames: ['Arial', 'Comic Sans MS','맑은 고딕','궁서','굴림','돋음체','바탕'],
    fontSizes: ['8','9','10','11','12','14','16','18','20','22','24','28','30','36','50','72'],
    maximumImageFileSize:2097152,

  popover: {
                  image: [
                    ['image', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']],
                    ['float', ['floatLeft', 'floatRight', 'floatNone']],
                    ['remove', ['removeMedia']]
                  ],
                  link: [
                    ['link', ['linkDialogShow', 'unlink']]
                  ],
                  table: [
                    ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
                    ['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
                  ],
                  air: [
                    ['color', ['color']],
                    ['font', ['bold', 'underline', 'clear']],
                    ['para', ['ul', 'paragraph']],
                    ['table', ['table']],
                    ['insert', ['link', 'picture']]
                  ]
                }
      });
$('.dropdown-toggle').dropdown()
    </script>