diff --git a/README-1.png b/README-1.png new file mode 100644 index 0000000..d7f0fad Binary files /dev/null and b/README-1.png differ diff --git a/README.md b/README.md index fb06083..8a0a895 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,50 @@ # butler_ddochi -### dev_0.0.21 -사이드메뉴에 unity 게임 등록. -* 쿠버네티스에 배포된 웹 게임 링크 등록. -* 쿠버네티스 클러스터에 배포된 웹 게임 및 istio 설정 필요. \ No newline at end of file +butler_ddochi는 개인 테스트 환경 관리를 위한 목적으로 만들어지고 있습니다. +* 클라우드 네이티브 환경을 이용한 서비스 환경 관리 +* 쿠버네티스 관리 +* 문의는 icurfer@gmail.com으로 부탁드립니다. + +> 문서가 미흡하여 설치 및 구성이 어려울 수 있습니다. + +--- + +## 목차 + +* [사전 구성요소 선택](#사전-구성-컴포넌트(선택)) +* [butler_ddochi설치](#butler_ddochi설치) + +### 사전 구성 컴포넌트(필수) +동작을 위한 최소한의 필수 컴포넌트입니다. +* MariaDB +* MinIO + +### 사전 구성 컴포넌트(선택) +아래 컴포넌트들이 배포 되어있다면, 로그인 후 Edit Profile을 이용하여 웹콘솔 링크를 입력하여 사용합니다. +![alt text](README-1.png) +* Gitea +* Harbor +* ArgoCD +* CodeServer +* Rancher +* Prometheus +* OpenSearch +* Kiali +--- + +### butler_ddochi설치 +docker 또는 kubernetes를 이용하여 배포 합니다. + +> docker pull harbor.icurfer.com/py_prj/butler_ddochi:${version} + +필수 환경변수 +* DEBUG=0 +* SQL_ENGINE='django.db.backends.mysql' +* SQL_HOST='DB_SVR_address' +* SQL_USER='DB_SVR_user' +* SQL_PASSWORD='DB_SVR_user_password' +* SQL_DATABASE='DB_SVR_database' +* SQL_PORT='DB_SVR_portnumber' +* CSRF_TRUSTED_ORIGINS=https://www.example.com,https://butler.example.com,https://butler.example.com:8000 +* MM_URL=https://mm.example.com/hooks/${hash} +* (기능 미구현)MINIO_URL=https://minio.example.com/ \ No newline at end of file diff --git a/blog/migrations/0006_alter_post_author.py b/blog/migrations/0006_alter_post_author.py new file mode 100644 index 0000000..6da1f62 --- /dev/null +++ b/blog/migrations/0006_alter_post_author.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.14 on 2025-01-25 14:39 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('blog', '0005_rename_content_post_contents'), + ] + + operations = [ + migrations.AlterField( + model_name='post', + name='author', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='blog_posts', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/blog/models.py b/blog/models.py index bd6e088..eb0d7d7 100644 --- a/blog/models.py +++ b/blog/models.py @@ -1,5 +1,6 @@ from django.db import models from django.conf import settings +from django.urls import reverse from markdown_it import MarkdownIt from taggit.managers import TaggableManager @@ -10,12 +11,20 @@ class Post(models.Model): created_at = models.DateTimeField(auto_now_add=True) # 작성일 updated_at = models.DateTimeField(auto_now=True) # 수정일 tags = TaggableManager() - author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE) + author = models.ForeignKey( + settings.AUTH_USER_MODEL, + null=True, + on_delete=models.CASCADE, + related_name='blog_posts' + ) def render_markdown(self): """마크다운을 HTML로 변환""" md = MarkdownIt() return md.render(self.contents) + + def get_absolute_url(self): + return reverse('blog:post_detail', args=[str(self.pk)]) def __str__(self): return self.title \ No newline at end of file diff --git a/blog/templates/blog/create_post copy.html b/blog/templates/blog/create_post copy.html deleted file mode 100644 index 57f3ee3..0000000 --- a/blog/templates/blog/create_post copy.html +++ /dev/null @@ -1,39 +0,0 @@ -{% extends "components/base.html" %} -{% block title %}Create Post{% endblock %} - -{% block main_area %} -

Create New Post

-
- -
-
- {% csrf_token %} - {{ form.as_p }} - -
-
- - -
-

Preview

-
-
-
- - - - -{% endblock %} diff --git a/blog/templates/blog/create_post.html b/blog/templates/blog/create_post.html index 2d2e43e..e5736cd 100644 --- a/blog/templates/blog/create_post.html +++ b/blog/templates/blog/create_post.html @@ -22,7 +22,7 @@ -

contents

+

Contents

{{ form.contents }} @@ -41,9 +41,22 @@ + + - {% endblock %} +
+{% endblock %} diff --git a/butler/templates/butler/create_notice.html b/blog/templates/blog/create_post_default.html similarity index 79% rename from butler/templates/butler/create_notice.html rename to blog/templates/blog/create_post_default.html index a6d4bde..2d2e43e 100644 --- a/butler/templates/butler/create_notice.html +++ b/blog/templates/blog/create_post_default.html @@ -1,8 +1,8 @@ {% extends "components/base.html" %} -{% block title %}Create Notice{% endblock %} +{% block title %}Create Post{% endblock %} {% block main_area %} -

Create New Notice

+

Create New Post

@@ -12,6 +12,14 @@ {{ form.title.label_tag }} {{ form.title }}
+
+ {{ form.summary.label_tag }} + {{ form.summary }} +
+
+ {{ form.tags.label_tag }} + {{ form.tags }} +

contents

@@ -22,7 +30,7 @@
- Cancel + Cancel
diff --git a/blog/templates/blog/post_detail.html b/blog/templates/blog/post_detail.html index 8ad9679..ece3dad 100644 --- a/blog/templates/blog/post_detail.html +++ b/blog/templates/blog/post_detail.html @@ -8,8 +8,11 @@
{{ post.summary }}
{% endif %} -
{{ post.created_at }}
- by. {{ post.author | upper }}
+
{{ post.created_at }} +
+ by. + {{ post.author | upper }}
+
{{ post.render_markdown|safe }}
@@ -22,5 +25,43 @@

{% endif %} - Back to List + + {% if request.user == post.author %} +
+ List + Edit +
+ {% csrf_token %} + +
+
+ {% endif %} + + + + + + + + {% endblock %} \ No newline at end of file diff --git a/blog/templates/blog/post_detail_default.html b/blog/templates/blog/post_detail_default.html new file mode 100644 index 0000000..05c6929 --- /dev/null +++ b/blog/templates/blog/post_detail_default.html @@ -0,0 +1,31 @@ +{% extends "components/base.html" %} +{% block title %}Post{% endblock %} + +{% block main_area %} + +

{{ post.title }}

+ {% if post.summary %} +
{{ post.summary }}
+ {% endif %} + +
{{ post.created_at }} +
+ by. + {{ post.author | upper }}
+
+ {{ post.render_markdown|safe }} +
+
+ {% if post.tags.exists %} + + {% for tag in post.tags.all %} + {{ tag }} + {% endfor %} +
+
+ {% endif %} + List + {% if request.user == post.author %} + Edit + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/blog/templates/blog/post_list.html b/blog/templates/blog/post_list.html index 2036063..2dcb66e 100644 --- a/blog/templates/blog/post_list.html +++ b/blog/templates/blog/post_list.html @@ -12,7 +12,7 @@
  • {{ post.title }}

    {{ post.summary }}

    - Read More + Read More
  • {% endfor %} diff --git a/blog/templates/blog/update_post.html b/blog/templates/blog/update_post.html new file mode 100644 index 0000000..ec4adaf --- /dev/null +++ b/blog/templates/blog/update_post.html @@ -0,0 +1,58 @@ +{% extends "components/base.html" %} +{% block title %}Update Post{% endblock %} + +{% block main_area %} +

    Update Post

    +
    +
    +
    +
    + {% csrf_token %} +
    + {{ form.title.label_tag }} + {{ form.title }} +
    +
    + {{ form.summary.label_tag }} + {{ form.summary }} +
    +
    + {{ form.tags.label_tag }} + {{ form.tags }} +
    + + +

    Contents

    +
    + {{ form.contents }} +
    + +
    + + Cancel +
    +
    +
    +
    +
    +
    +
    + + + + +
    +{% endblock %} diff --git a/blog/urls.py b/blog/urls.py index 05da17f..fec8db1 100644 --- a/blog/urls.py +++ b/blog/urls.py @@ -7,4 +7,6 @@ urlpatterns = [ path('', views.post_list, name='post_list'), # 포스트 리스트 path('create/', views.create_post, name='create_post'), # 포스트 작성 path('/', views.post_detail, name='post_detail'), # 포스트 상세 보기 + path('/update/', views.update_post, name='update_post'), # 글 수정 URL + path('/delete/', views.delete_post, name='delete_post'), # 삭제 URL ] \ No newline at end of file diff --git a/blog/views.py b/blog/views.py index 645d927..995be15 100644 --- a/blog/views.py +++ b/blog/views.py @@ -3,6 +3,16 @@ from django.contrib.auth.decorators import login_required from .models import Post from .forms import PostForm +# 게시글 목록 +def post_list(request): + posts = Post.objects.all().order_by('-created_at') + return render(request, 'blog/post_list.html', {'posts': posts}) + +# 게시글 상세 보기 +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) + @login_required def create_post(request): if request.method == 'POST': @@ -17,10 +27,37 @@ def create_post(request): form = PostForm() return render(request, 'blog/create_post.html', {'form': form}) -def post_list(request): - posts = Post.objects.all().order_by('-created_at') - return render(request, 'blog/post_list.html', {'posts': posts}) -def post_detail(request, pk): + +@login_required +def update_post(request, pk): post = get_object_or_404(Post, pk=pk) - return render(request, 'blog/post_detail.html', {'post': post}) + + # 작성자만 수정 가능하도록 권한 검사 + if post.author != request.user: + return redirect('blog:post_list') + + if request.method == 'POST': + form = PostForm(request.POST, instance=post) + if form.is_valid(): + form.save() + return redirect('blog:post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + + return render(request, 'blog/update_post.html', {'form': form, 'post': post}) + +@login_required +def delete_post(request, pk): + post = get_object_or_404(Post, pk=pk) + + # 작성자만 삭제 가능 + if post.author != request.user: + return redirect('blog:post_list') + + # POST 요청일 때 삭제 + if request.method == 'POST': + post.delete() + return redirect('blog:post_list') + + return render(request, 'blog/confirm_delete.html', {'post': post}) \ No newline at end of file diff --git a/board_notice/__init__.py b/board_notice/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/board_notice/admin.py b/board_notice/admin.py new file mode 100644 index 0000000..d69a4af --- /dev/null +++ b/board_notice/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import BoardNotice + +admin.site.register(BoardNotice) diff --git a/board_notice/apps.py b/board_notice/apps.py new file mode 100644 index 0000000..beb3a1c --- /dev/null +++ b/board_notice/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class BoardNoticeConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'board_notice' diff --git a/board_notice/forms.py b/board_notice/forms.py new file mode 100644 index 0000000..954c181 --- /dev/null +++ b/board_notice/forms.py @@ -0,0 +1,11 @@ +from django import forms +from .models import BoardNotice + +class BoardNoticeForm(forms.ModelForm): + class Meta: + model = BoardNotice + fields = ['title', 'contents'] + widgets = { + 'title': forms.TextInput(attrs={'class': 'form-control'}), + 'contents': forms.Textarea(attrs={'class': 'form-control', 'id': 'markdown-editor'}), + } diff --git a/board_notice/migrations/0001_initial.py b/board_notice/migrations/0001_initial.py new file mode 100644 index 0000000..8ef3515 --- /dev/null +++ b/board_notice/migrations/0001_initial.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.14 on 2025-01-25 14:39 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='BoardNotice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('contents', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('author', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='board_notice', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/board_notice/migrations/__init__.py b/board_notice/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/board_notice/models.py b/board_notice/models.py new file mode 100644 index 0000000..4841e3d --- /dev/null +++ b/board_notice/models.py @@ -0,0 +1,27 @@ +from django.db import models +from django.conf import settings +from django.urls import reverse +from markdown_it import MarkdownIt + +class BoardNotice(models.Model): + title = models.CharField(max_length=200) # 제목 + contents = models.TextField() # 본문 (마크다운 저장) + created_at = models.DateTimeField(auto_now_add=True) # 작성일 + updated_at = models.DateTimeField(auto_now=True) # 수정일 + author = models.ForeignKey( + settings.AUTH_USER_MODEL, + null=True, + on_delete=models.CASCADE, + related_name='board_notice' + ) + + def render_markdown(self): + """마크다운을 HTML로 변환""" + md = MarkdownIt() + return md.render(self.contents) + + def get_absolute_url(self): + return reverse('board_notice:notice_detail', args=[str(self.pk)]) + + def __str__(self): + return self.title \ No newline at end of file diff --git a/board_notice/templates/board_notice/create_notice.html b/board_notice/templates/board_notice/create_notice.html new file mode 100644 index 0000000..9eb3306 --- /dev/null +++ b/board_notice/templates/board_notice/create_notice.html @@ -0,0 +1,72 @@ +{% extends "components/base.html" %} +{% block title %}Create Notice{% endblock %} + +{% block main_area %} +

    Create New Notice

    +
    +
    +
    +
    + {% csrf_token %} +
    + {{ form.title.label_tag }} + {{ form.title }} +
    + + +

    Contents

    + +
    + {{ form.contents }} +
    + +
    + + Cancel +
    +
    +
    +
    +
    +
    +
    + + + + + + +
    +{% endblock %} diff --git a/board_notice/templates/board_notice/notice_detail.html b/board_notice/templates/board_notice/notice_detail.html new file mode 100644 index 0000000..069c086 --- /dev/null +++ b/board_notice/templates/board_notice/notice_detail.html @@ -0,0 +1,56 @@ +{% extends "components/base.html" %} +{% block title %}Notice{% endblock %} + +{% block main_area %} + +

    {{ notice.title }}

    + +
    {{ notice.created_at }} +
    + by. + {{ notice.author | upper }}
    + +
    + {{ notice.render_markdown|safe }} +
    +
    + + {% if request.user == notice.author %} +
    + List + Edit +
    + {% csrf_token %} + +
    +
    + {% endif %} + + + + + + + + +{% endblock %} \ No newline at end of file diff --git a/butler/templates/butler/notice_list.html b/board_notice/templates/board_notice/notice_list.html similarity index 69% rename from butler/templates/butler/notice_list.html rename to board_notice/templates/board_notice/notice_list.html index e48e3aa..a1ce78b 100644 --- a/butler/templates/butler/notice_list.html +++ b/board_notice/templates/board_notice/notice_list.html @@ -5,27 +5,31 @@ {% block main_area %}

    공지사항 - +

    - {% if records %} + {% if notices %} + - {% for record in records %} + {% for record in notices %} + @@ -36,9 +40,9 @@

    현재 공지사항이 없습니다.

    {% endif %} {% if request.user.is_authenticated %} - - + + {% endif %} {% endblock %} diff --git a/board_notice/templates/board_notice/update_notice.html b/board_notice/templates/board_notice/update_notice.html new file mode 100644 index 0000000..ec4adaf --- /dev/null +++ b/board_notice/templates/board_notice/update_notice.html @@ -0,0 +1,58 @@ +{% extends "components/base.html" %} +{% block title %}Update Post{% endblock %} + +{% block main_area %} +

    Update Post

    +
    +
    +
    +
    + {% csrf_token %} +
    + {{ form.title.label_tag }} + {{ form.title }} +
    +
    + {{ form.summary.label_tag }} + {{ form.summary }} +
    +
    + {{ form.tags.label_tag }} + {{ form.tags }} +
    + + +

    Contents

    +
    + {{ form.contents }} +
    + +
    + + Cancel +
    + +
    +
    +
    +
    +
    + + + + +
    +{% endblock %} diff --git a/board_notice/tests.py b/board_notice/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/board_notice/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/board_notice/urls.py b/board_notice/urls.py new file mode 100644 index 0000000..0ea5fc5 --- /dev/null +++ b/board_notice/urls.py @@ -0,0 +1,12 @@ +from django.urls import path +from . import views + +app_name = 'board_notice' + +urlpatterns = [ + path('', views.notice_list, name='notice_list'), # 포스트 리스트 + path('create/', views.create_notice, name='create_notice'), # 포스트 작성 + path('/', views.notice_detail, name='notice_detail'), # 포스트 상세 보기 + path('/update/', views.update_notice, name='update_notice'), # 글 수정 URL + path('/delete/', views.delete_notice, name='delete_notice'), # 삭제 URL +] \ No newline at end of file diff --git a/board_notice/views.py b/board_notice/views.py new file mode 100644 index 0000000..51b15dc --- /dev/null +++ b/board_notice/views.py @@ -0,0 +1,62 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.contrib.auth.decorators import login_required +from .models import BoardNotice +from .forms import BoardNoticeForm + +# 게시글 목록 +def notice_list(request): + notices = BoardNotice.objects.all().order_by('-created_at') + return render(request, 'board_notice/notice_list.html', {'notices': notices}) + +# 게시글 상세 보기 +def notice_detail(request, pk): + notice = get_object_or_404(BoardNotice, pk=pk) + return render(request, 'board_notice/notice_detail.html', {'notice': notice}) + +# 공지사항 게시글 등록 +@login_required +def create_notice(request): + if request.method == 'POST': + form = BoardNoticeForm(request.POST) + if form.is_valid(): + notice = form.save(commit=False) + notice.author = request.user # 작성자 정보 추가 + notice.save() + return redirect('board_notice:notice_list') + else: + form = BoardNoticeForm() + return render(request, 'board_notice/create_notice.html', {'form': form}) + +# 공지사항 게시글 수정 +@login_required +def update_notice(request, pk): + notice = get_object_or_404(BoardNotice, pk=pk) + + # 작성자만 수정 가능하도록 권한 검사 + if notice.author != request.user: + return redirect('board_notice:notice_list') + + if request.method == 'POST': + form = BoardNoticeForm(request.POST, instance=notice) + if form.is_valid(): + form.save() + return redirect('board_notice:notice_detail', pk=notice.pk) + else: + form = BoardNoticeForm(instance=notice) + + return render(request, 'board_notice/update_notice.html', {'form': form, 'notice': notice}) + +# 공지사항 게시글 삭제 +@login_required +def delete_notice(request, pk): + notice = get_object_or_404(BoardNotice, pk=pk) + + # 작성자만 삭제 가능하도록 권한 검사 + if notice.author != request.user: + return redirect('board_notice:notice_list') + + if request.method == 'POST': + notice.delete() + return redirect('board_notice:notice_list') + + return render(request, 'board_notice/confirm_delete.html', {'notice': notice}) diff --git a/butler/admin.py b/butler/admin.py index 5d574bd..8ac0366 100644 --- a/butler/admin.py +++ b/butler/admin.py @@ -1,5 +1,4 @@ from django.contrib import admin -from .models import IPManagementRecord, NoticeBoard +from .models import IPManagementRecord admin.site.register(IPManagementRecord) -admin.site.register(NoticeBoard) diff --git a/butler/forms.py b/butler/forms.py index f0281a1..e79048b 100644 --- a/butler/forms.py +++ b/butler/forms.py @@ -1,11 +1 @@ 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'}), - } diff --git a/butler/migrations/0003_rename_desc_ipmanagementrecord_contents.py b/butler/migrations/0003_rename_desc_ipmanagementrecord_contents.py new file mode 100644 index 0000000..1651174 --- /dev/null +++ b/butler/migrations/0003_rename_desc_ipmanagementrecord_contents.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.14 on 2025-01-25 11:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('butler', '0002_noticeboard'), + ] + + operations = [ + migrations.RenameField( + model_name='ipmanagementrecord', + old_name='desc', + new_name='contents', + ), + ] diff --git a/butler/models.py b/butler/models.py index 6e8274b..e0a736d 100644 --- a/butler/models.py +++ b/butler/models.py @@ -7,7 +7,7 @@ class IPManagementRecord(models.Model): network_nm = models.CharField(max_length=100) # NETWORK_NM ip_addrs = models.CharField(max_length=50) # IP_ADDRS svr_nm = models.CharField(max_length=100) # SVR_NM - desc = models.TextField(blank=True, null=True) # DESC + contents = models.TextField(blank=True, null=True) # DESC remark = models.TextField(blank=True, null=True) # REMARK created_at = models.DateTimeField(auto_now_add=True) # 생성 시간 자동 기록 updated_at = models.DateTimeField(auto_now=True) # 수정 시간 자동 기록 @@ -15,21 +15,4 @@ class IPManagementRecord(models.Model): author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE) def __str__(self): - return f'{self.network_nm} {self.ip_addrs} {self.svr_nm} {self.desc}' - - -class NoticeBoard(models.Model): - title = models.CharField(max_length=100) - contents = models.TextField(blank=True, null=True) - - created_at = models.DateTimeField(auto_now_add=True) # 생성 시간 자동 기록 - updated_at = models.DateTimeField(auto_now=True) # 수정 시간 자동 기록 - - author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE) - - def __str__(self): - return f'{self.title} {self.author} {self.created_at}' - - def get_absolute_url(self): - return reverse('butler:notice_detail', args=[str(self.pk)]) - # {{ record.title }} + return f'{self.network_nm} {self.ip_addrs} {self.svr_nm} {self.contents}' \ No newline at end of file diff --git a/butler/templates/butler/landing.html b/butler/templates/butler/landing.html index 67f8c15..af880d3 100644 --- a/butler/templates/butler/landing.html +++ b/butler/templates/butler/landing.html @@ -3,46 +3,46 @@ {% block title %}Landing Page{% endblock %} {% block main_area %} -
    -
    - -
    -

    Latest Notices

    -
    - {% for notice in notices %} -
    -
    -
    -
    {{ notice.title }}
    -

    {{ notice.content|truncatewords:20 }}

    - View Notice +
    +
    + +
    +

    Latest Notices

    +
    + {% for notice in board_notices %} +
    +
    +
    +
    {{ notice.title }}
    +

    {{ notice.contents|truncatechars:50 }}

    + View Notice +
    +
    -
    + {% empty %} +

    No notices available.

    + {% endfor %}
    - {% empty %} -

    No notices available.

    - {% endfor %}
    -
    - -
    -

    Latest Blog Posts

    -
    - {% for post in blog_posts %} -
    -
    -
    -
    {{ post.title }}
    -

    {{ post.summary|truncatewords:20 }}

    - Read More + +
    +

    Latest Blog Posts

    +
    + {% for post in blog_posts %} +
    +
    +
    +
    {{ post.title }}
    +

    {{ post.contents|truncatechars:50 }}

    + Read More +
    +
    -
    + {% empty %} +

    No blog posts available.

    + {% endfor %}
    - {% empty %} -

    No blog posts available.

    - {% endfor %}
    -
    {% endblock %} \ No newline at end of file diff --git a/butler/templates/butler/notice_detail.html b/butler/templates/butler/notice_detail.html deleted file mode 100644 index c6729bb..0000000 --- a/butler/templates/butler/notice_detail.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "components/base.html" %} - -{% block title %}Notice Detail{% endblock %} - -{% block main_area %} -

    {{ notice.title }}

    -
    -
    - {{ notice.contents|linebreaks }} -
    -
    -

    작성자: - {{ notice.author }}

    -

    작성일: - {{ notice.created_at|date:"Y-m-d H:i" }}

    -

    수정일: - {{ notice.updated_at|date:"Y-m-d H:i" }}

    - Back to Notices -{% endblock %} diff --git a/butler/urls.py b/butler/urls.py index d27a261..2c5c0df 100644 --- a/butler/urls.py +++ b/butler/urls.py @@ -8,9 +8,9 @@ urlpatterns = [ # Landing Page path('', views.LandingPageView.as_view(), name='landing'), # 클래스 기반 뷰(CBV) 호출 - path('notice', views.notice_list, name='notice_list'), - path('create_notice/', views.create_notice, name='create_notice'), # 포스트 작성 - path('notice//', views.notice_detail_view, name='notice_detail'), + # path('notice', views.notice_list, name='notice_list'), + # path('create_notice/', views.create_notice, name='create_notice'), # 포스트 작성 + # path('notice//', views.notice_detail_view, name='notice_detail'), 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/delete/', views.delete_ip_records, name='ip_mgmt_delete'), # 삭제 URL 추가 diff --git a/butler/views.py b/butler/views.py index 926518a..e9d73d8 100644 --- a/butler/views.py +++ b/butler/views.py @@ -4,9 +4,9 @@ from django.views.generic import TemplateView from pathlib import Path import markdown import os -from .models import NoticeBoard, IPManagementRecord +from .models import IPManagementRecord from blog.models import Post -from .forms import PostForm +from board_notice.models import BoardNotice from django.db.models import Q @@ -15,39 +15,11 @@ class LandingPageView(TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + # context['var'] var를 templates로 전달해서 보여지는 것. context['blog_posts'] = Post.objects.order_by('-created_at')[:3] - context['notices'] = NoticeBoard.objects.order_by('-created_at')[:3] + context['board_notices'] = BoardNotice.objects.order_by('-created_at')[:3] return context -# --- notice --- -@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() - return render(request, "butler/notice_list.html", {"records": records}) - - -def notice_detail_view(request, pk): - try: - notice = NoticeBoard.objects.get(pk=pk) - except NoticeBoard.DoesNotExist: - return render(request, "404.html") # 선택적으로 에러 처리 - - return render(request, "butler/notice_detail.html", {"notice": notice}) - - # --- ip management --- # def ip_mgmt_view(request): # # records = IPManagementRecord.objects.all() diff --git a/butler_ddochi/settings.py b/butler_ddochi/settings.py index b089e70..b86905c 100644 --- a/butler_ddochi/settings.py +++ b/butler_ddochi/settings.py @@ -41,6 +41,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'taggit', # Custom by.icurfer + 'board_notice', 'custom_auth', 'butler', 'blog', diff --git a/butler_ddochi/urls.py b/butler_ddochi/urls.py index a467b51..949e2b3 100644 --- a/butler_ddochi/urls.py +++ b/butler_ddochi/urls.py @@ -24,10 +24,11 @@ urlpatterns = [ path('', include('butler.urls')), path('admin/', admin.site.urls), path('accounts/', include('custom_auth.urls')), # custom_auth URL 추가 + path('notice/', include('board_notice.urls')), + path('blog/', include('blog.urls')), path('nhncloud/', include('nhncloud.urls')), path('nhnc_mgmt/', include('nhnc_mgmt.urls')), path('mm_msg/', include('mm_msg.urls')), - path('blog/', include('blog.urls')), path('ansible_manager/', include('ansible_manager.urls')), ] diff --git a/version b/version index 0225d87..50bcd07 100644 --- a/version +++ b/version @@ -1 +1 @@ -dev_0.0.24 \ No newline at end of file +dev_0.0.25 \ No newline at end of file
    글번호 제목내용 작성자 작성일
    {{ record.pk }} {{ record.title }} + {{ record.contents|truncatechars:50 }} + {{ record.author }} {{ record.created_at|date:"Y-m-d H:i" }}