summernote 공식 문서
summernote github
poetry add django-summernote 
from config import settings
from django.conf import settings
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
from config import settingsfrom django.conf import settingssettings.DEBUG: 가 있는 이유 
admin.py 에서 SummernoteModelAdmin을 상속

이미지가 제대로 보이도록 blog_detail.html 코드를 수정



# summernote option (불필요한 부분 제거 )
SUMMERNOTE_CONFIG = {
# Or, you can set it to `False` to use SummernoteInplaceWidget by default - no iframe mode
# In this case, you have to load Bootstrap/jQuery sources and dependencies manually.
# Use this when you're already using Bootstrap/jQuery based themes.
'iframe': False,
# You can put custom Summernote settings
'summernote': {
# As an example, using Summernote Air-mode
'airMode': False,
# Change editor size
'width': '100%',
'height': '480',
# Use proper language setting automatically (default)
# Toolbar customization
# https://summernote.org/deep-dive/#custom-toolbar-popover
'toolbar': [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['fontname', ['fontname']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture', ]],
['view', ['fullscreen', 'help']],
],
# Or, explicitly set language/locale for editor
'lang': 'ko-KR',
# You can also add custom settings for external plugins
# 'print': {
# 'stylesheetUrl': '/some_static_folder/printable.css',
# },
'codemirror': {
'mode': 'htmlmixed',
'lineNumbers': 'true',
# You have to include theme file in 'css' or 'css_for_inplace' before using it.
'theme': 'monokai',
},
},
# Require users to be authenticated for uploading attachments.
'attachment_require_authentication': True,
# You can completely disable the attachment feature.
'disable_attachment': False,
# Set to `False` to return attachment paths in relative URIs.
'attachment_absolute_uri': True,
# test_func in summernote upload view. (Allow upload images only when user passes the test)
# https://docs.djangoproject.com/en/2.2/topics/auth/default/#django.contrib.auth.mixins.UserPassesTestMixin
# You can add custom css/js for SummernoteWidget.
}

models.py 에 이미지 필드를 추가
Image를 사용하기 위한 Pillow 라이브러리를 설치 필요
poetry add pillow모델을 수정했기때문에 마이그레이션 파일을 만들고 마이그레이트

admin 페이지에서는 확인 완료

fields = ('category', 'title', 'image', 'content')

class BlogUpdateView(LoginRequiredMixin, UpdateView):
model = Blog
template_name = 'blog_form.html'
form_class = BlogForm
.
.
.
# 추가
def form_valid(self, form):
print(form.cleaned_data)
return super().form_valid(form)
.
.
.
# blog_list.html
{% for blog in object_list %}
<div class="my-1">
{# 수정 #}
<a href="{% url 'blog:detail' blog.pk %}" class="link-primary link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover row">
{% if blog.image %}
<img src="{{ blog.image.url }}" alt="" class="col-2">
{% endif %}
<span class="col-10">
[{{ blog.get_category_display }}] {{ blog.title }} - <small>{{ blog.created_at | date:"Y-m-d" }}</small>
</span>
</a>
</div>
{% endfor %}
# # blog_detail.html
<div style="text-align: right">
{{ blog.author.username }}
</div>
<hr>
<img src="{{ blog.image.url }}" alt="" class="w-100"> {# 추가 #}

# 이미지가 제대로 들어오는지 테스트
if form.is_vaild():
print(form.cleaned_data)





이미지가 포함된 게시글은 목록페이지에서 제목 옆에 이미지가 보이도록 만들기





DB 설계 시에는, 중복 데이터를 최소한으로 하는 것이 가장 중요
FK 등을 적절히 활용해야 하며 텍스트보다는 숫자가 가볍기 때문에 숫자 데이터로 갖고 있는 것을 권장
숫자