notice 등록 기능 구현

This commit is contained in:
sdjo 2025-01-17 15:41:11 +09:00
parent 150046da1d
commit 819d554bac
10 changed files with 115 additions and 11 deletions

View File

@ -5,10 +5,10 @@ from .models import Post
class PostForm(forms.ModelForm): class PostForm(forms.ModelForm):
class Meta: class Meta:
model = Post model = Post
fields = ['title', 'content', 'summary', 'tags'] fields = ['title', 'contents', 'summary', 'tags']
widgets = { widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}), 'title': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'id': 'markdown-editor'}), 'contents': forms.Textarea(attrs={'class': 'form-control', 'id': 'markdown-editor'}),
'summary': forms.TextInput(attrs={'class': 'form-control'}), 'summary': forms.TextInput(attrs={'class': 'form-control'}),
'tags': TagWidget(attrs={'class': 'form-control', 'placeholder': 'Add tags'}), 'tags': TagWidget(attrs={'class': 'form-control', 'placeholder': 'Add tags'}),
} }

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.14 on 2025-01-17 15:36
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('blog', '0004_remove_post_tags_post_tags'),
]
operations = [
migrations.RenameField(
model_name='post',
old_name='content',
new_name='contents',
),
]

View File

@ -5,7 +5,7 @@ from taggit.managers import TaggableManager
class Post(models.Model): class Post(models.Model):
title = models.CharField(max_length=200) # 제목 title = models.CharField(max_length=200) # 제목
content = models.TextField() # 본문 (마크다운 저장) contents = models.TextField() # 본문 (마크다운 저장)
summary = models.CharField(max_length=2000, blank=True, null=True) # 요약 summary = models.CharField(max_length=2000, blank=True, null=True) # 요약
created_at = models.DateTimeField(auto_now_add=True) # 작성일 created_at = models.DateTimeField(auto_now_add=True) # 작성일
updated_at = models.DateTimeField(auto_now=True) # 수정일 updated_at = models.DateTimeField(auto_now=True) # 수정일
@ -15,7 +15,7 @@ class Post(models.Model):
def render_markdown(self): def render_markdown(self):
"""마크다운을 HTML로 변환""" """마크다운을 HTML로 변환"""
md = MarkdownIt() md = MarkdownIt()
return md.render(self.content) return md.render(self.contents)
def __str__(self): def __str__(self):
return self.title return self.title

View File

@ -25,7 +25,7 @@
<h2>contents</h2> <h2>contents</h2>
<div class="col-md-12"> <div class="col-md-12">
{{ form.content }} {{ form.contents }}
</div> </div>
<!-- 버튼 --> <!-- 버튼 -->
<div class="d-flex justify-content-end mt-4"> <div class="d-flex justify-content-end mt-4">

11
butler/forms.py Normal file
View File

@ -0,0 +1,11 @@
from django import forms
from .models import NoticeBoard
class PostForm(forms.ModelForm):
class Meta:
model = NoticeBoard
fields = ['title', 'contents']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'contents': forms.Textarea(attrs={'class': 'form-control', 'id': 'markdown-editor'}),
}

View File

@ -0,0 +1,50 @@
{% extends "components/base.html" %}
{% block title %}Create Notice{% endblock %}
{% block main_area %}
<h1 class="pt-3">Create New Notice</h1>
<div class="container">
<div class="row">
<div class="col-md-6">
<form method="POST" id="post-form">
{% csrf_token %}
<div class="mb-3">
{{ form.title.label_tag }}
{{ form.title }}
</div>
<!-- 마크다운 에디터 -->
<h2>contents</h2>
<div class="col-md-12">
{{ form.contents }}
</div>
<!-- 버튼 -->
<div class="d-flex justify-content-end mt-4">
<button type="submit" class="btn btn-primary me-2">Create Post</button>
<a href="{% url 'butler:notice_list' %}" class="btn btn-secondary">Cancel</a>
</div>
</form>
</div>
<div class="col-md-6">
<div id="preview" class="border p-3 bg-light h-100 overflow-auto"></div>
</div>
</div>
<!-- 마크다운 파서 및 스크립트 -->
<script src="https://cdn.jsdelivr.net/npm/markdown-it/dist/markdown-it.min.js"></script>
<script>
// 마크다운 파서 초기화
const md = window.markdownit();
// content 필드와 미리보기 연결
const textarea = document.getElementById("markdown-editor");
const preview = document.getElementById("preview");
// 실시간 미리보기 업데이트
textarea.addEventListener("input", function () {
const markdownContent = textarea.value; // textarea 내용 가져오기
preview.innerHTML = md.render(markdownContent); // 마크다운 -> HTML 변환
});
</script>
{% endblock %}

View File

@ -15,5 +15,5 @@
{{ notice.created_at|date:"Y-m-d H:i" }}</p> {{ notice.created_at|date:"Y-m-d H:i" }}</p>
<p class="text-muted">수정일: <p class="text-muted">수정일:
{{ notice.updated_at|date:"Y-m-d H:i" }}</p> {{ notice.updated_at|date:"Y-m-d H:i" }}</p>
<a href="{% url 'butler:notice' %}" class="btn btn-secondary mt-3">Back to Notices</a> <a href="{% url 'butler:notice_list' %}" class="btn btn-secondary mt-3">Back to Notices</a>
{% endblock %} {% endblock %}

View File

@ -3,7 +3,10 @@
{% block title %}Notice{% endblock %} {% block title %}Notice{% endblock %}
{% block main_area %} {% block main_area %}
<h2 class="fw-bold pt-3 pb-2">공지사항</h2> <h2 class="fw-bold pt-3 pb-2 d-flex justify-content-between">
공지사항
</h2>
<!-- 공지사항 목록 --> <!-- 공지사항 목록 -->
{% if records %} {% if records %}
@ -32,4 +35,10 @@
{% else %} {% else %}
<p class="text-muted">현재 공지사항이 없습니다.</p> <p class="text-muted">현재 공지사항이 없습니다.</p>
{% endif %} {% endif %}
{% if request.user.is_authenticated %}
<!-- 버튼 컨테이너 -->
<div class="d-flex justify-content-between align-items-center mb-3">
<a href="{% url 'butler:create_notice' %}" class="btn btn-primary">Create Notice</a>
</div>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -5,7 +5,8 @@ app_name = 'butler'
urlpatterns = [ urlpatterns = [
path('', views.hello_view, name='landing'), # 루트 경로에서 hello_view 호출 path('', views.hello_view, name='landing'), # 루트 경로에서 hello_view 호출
path('notice', views.notice_view, name='notice'), path('notice', views.notice_list, name='notice_list'),
path('create_notice/', views.create_notice, name='create_notice'), # 포스트 작성
path('notice/<int:pk>/', views.notice_detail_view, name='notice_detail'), path('notice/<int:pk>/', views.notice_detail_view, name='notice_detail'),
path('ip_mgmt', views.ip_mgmt_view, name='ip_mgmt'), path('ip_mgmt', views.ip_mgmt_view, name='ip_mgmt'),
path('ip-mgmt/add/', views.add_ip_record, name='ip_mgmt_add'), # 데이터 추가 경로 path('ip-mgmt/add/', views.add_ip_record, name='ip_mgmt_add'), # 데이터 추가 경로

View File

@ -1,8 +1,10 @@
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from pathlib import Path from pathlib import Path
import markdown import markdown
import os import os
from .models import NoticeBoard, IPManagementRecord from .models import NoticeBoard, IPManagementRecord
from .forms import PostForm
from django.db.models import Q from django.db.models import Q
@ -12,11 +14,24 @@ def hello_view(request):
"butler/landing.html", "butler/landing.html",
) )
# --- notice --- # --- notice ---
def notice_view(request): @login_required
def create_notice(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user # 작성자 정보 추가
post.save()
form.save_m2m()
return redirect('butler:notice_list')
else:
form = PostForm()
return render(request, 'butler/create_notice.html', {'form': form})
def notice_list(request):
records = NoticeBoard.objects.all() records = NoticeBoard.objects.all()
return render(request, "butler/notice.html", {"records": records}) return render(request, "butler/notice_list.html", {"records": records})
def notice_detail_view(request, pk): def notice_detail_view(request, pk):