"파이썬 유치원 (어린이반)"의 두 판 사이의 차이

(같은 사용자의 중간 판 2개는 보이지 않습니다)
5,144번째 줄: 5,144번째 줄:
<gallery>
<gallery>
댓글기능활성화.png | Disqus 활용한 댓글 모델링
댓글기능활성화.png | Disqus 활용한 댓글 모델링
</gallery>
* 글 내용에서 행이 바뀌면 문단으로 변환
templates > blog > post_detail.html
<source lang="html">
<div class="content-wrap content-660 center-relative">
                <div class="wrap-blockquot">
                    {{ post.content|linebreaksbr }}
                </div>
            </div>
</source>
* 로그인 후 index 페이지 수정
<source lang="python">
{% if user.is_authenticated %}
            <div style="text-align: center; color: wheat; font-size: 40px; margin-top: 20px;">
                <i class="far fa-id-badge"> {{user.get_username}} </i>
            </div>
            {% else %}
            <div style="text-align: center; color: white; font-size: 40px; margin-top: 20px;">
                <i class="far fa-id-badge"></i>
            </div>
            {% endif %}
            <div class="site-info-holder">
                <p class="site-description">
                    Language : Python - Django<br>
                    Coder : AnKiWoong<br>
                </p>
            </div>
</source>
<gallery>
관리자 로그인 후 페이지.png|페이지
</gallery>
</gallery>


5,601번째 줄: 5,634번째 줄:
* 수정 버전 녹화
* 수정 버전 녹화
{{youtube|8Pk71vMjlT0}}
{{youtube|8Pk71vMjlT0}}
* 최종 버전 녹화
{{youtube|G85t0_NrO7Q}}


* 배포 주소 : http://anjia.pythonanywhere.com/blog/
* 배포 주소 : http://anjia.pythonanywhere.com/blog/
====댓글====
====댓글====
* 김왼손: 안기웅님은 워낙 잘하셔서 제가 드릴 말씀이 없네요. :)
* 김왼손: 안기웅님은 워낙 잘하셔서 제가 드릴 말씀이 없네요. :)

2020년 5월 26일 (화) 21:25 판

1 파이썬 유치원

파이썬 유치원은 유튜브 채널 김왼손의 왼손코딩에서 구독자와 함께 진행하는 프로젝트입니다. 프로젝트 기간 동안 스스로 학습하면서 나만의 프로그램을 만들어 봅니다. 파이썬 유치원 1기는 2020년 5월 1일부터 31일까지 한달 동안 진행합니다.

파이썬 유치원에는 강의가 없습니다. 사실 강의만 들어서는 머리에 남는 게 없습니다. 직접 만들어 봐야 합니다. 모든 분야가 그렇겠지만 코딩은 더욱 그렇습니다. 이제 강의는 그만 듣고 직접 만들어 봅시다. 모든 정보는 유튜브와 구글에 있으니까요. 파이썬 유치원에서는 방향과 방법을 함께 고민합니다. 유치원 선생님은 아이가 하고 싶은 대로 자유롭게 두면서 아이가 흥미를 잃지 않게, 다치지 않게 옆에서 도와줍니다. 파이썬 유치원에서의 김왼손은 그런 역할입니다.

파이썬 유치원의 모든 진행 상황은 유튜브 채널 김왼손의 왼손코딩에서 공유합니다. 매주 토요일 저녁 유튜브 라이브에서 어떻게 하고 있는지 함께 살펴보고 어려움이 있다면 함께 고민합니다. 각자의 진행 내용은 제타위키의 파이썬 유치원 문서에서 공유합니다. 진행 내용을 공유하고 서로 의견을 나눌 수 있습니다.

파이썬 유치원 어린이반은 파이썬이나 코딩을 어느정도 배웠고 프로그램을 만들어 본적인 있는 분들을 대상으로 합니다.

2 제타위키 사용법

3 어린이반 친구들

3.1 GreenElf

3.1.1 제목

제목을 정해주세요.

3.1.2 설명

유트브에서 볼려던 영상을 기억할 수 있도록 저장,유트브를 얼마나 볼지 설정,표시 vs studio code 사용 dev ed 참고함(코딩계 퓨디파이)단점:영어

3.1.3 실행화면

실행화면을 넣어주세요.

3.1.4 코드

import tkinter as tk
from tkinter import*
from tkinter import Place
from tkinter import messagebox
from tkinter import Text
import webbrowser
root = tk.Tk()
root.title("유트브 도우미 1.0")
root.geometry("400x400")
 
butima1=PhotoImage(file="hey.png")
#커맨드의 공간
def intro_message():
     messagebox.showinfo("유트브 도우미1.0에 대하여",message="설명")
#패트리온 계정 만들고 설명쓰기...
firsL=Entry(root,font = ("굴림",12))

messagebox.showinfo("안녕하세요","이런식으로 사용")
 #여기에다 부연설명
def urlin():
     webbrowser.open(e1)
     
#버튼들의 공간
btn1 = Button(root,image=butima1,command=urlin)
btn1.pack()
btn1.place(x=20, y=18)

btn2 = Button(root,image=butima1,command=urlin)
btn2.pack()
btn2.place(x=20, y=100)

intro=Button(root,text ="설명",bg="white",width="3",height=1,command=intro_message)
intro.pack()
intro.place(x=330,y=0)
#엔트리들의 공간
e1 = Entry(
     root,
     font=("굴림",12),

).pack(pady=20,ipadx=35,ipady=10)
 
url1=e1



e2 = Entry(
     root,
     font=("굴림",12),

).pack(pady=20,ipadx=35,ipady=10)


root.mainloop()

3.1.5 댓글

  • 김왼손: 어떤 프로그램이 나올지 기대되네요. :)

3.2 _ Starry8004

3.2.1 제목

제목을 정해주세요.

3.2.2 계획

검색과 복붙의 나날을 보내다 엄격한 자기 판단을 하고 유아반으로의 반배정을 신청 했으나 2020-05-01 김왼손님(김왼손의 왼손코딩)의 월반배정으로 어린이반으로. 목적성을 지닌 코딩을 해야 겠다 싶어 미드영어 공부를 위해 대본을 크롤링 해보자는 세부적인 목표 설정

3.2.3 설명

웹 크롤링

으아니 웨 ㅈㅔ가 어린이반이지유? ;ㅁ; 열띠미 해보게뜸미다

3.2.4 실행화면

실행화면을 넣어주세요.

3.2.5 코드

print('안녕 토끼야!')
from bs4 import BeautifulSoup
from urllib.request import urlopen

response = urlopen('https://www.naver.com/')
soup = BeautifulSoup(response, 'html.parser')
i = 1
f = open("새파일.txt", 'w')
for anchor in soup.select("span.keyword"):
    data = (str(i) + "위 : " + anchor.get_txt() + "\n"
i=i+1
f.write(data)
f.close()

3.2.6 github

https://github.com/starry8004

3.2.7 댓글

  • 김왼손: 실용적이고 구체적인 목표 좋습니다. :)

3.3 안기웅

3.3.1 제목

안지아의 성장블로그

3.3.2 About Me

안녕하세요. 비전공자 딸바보 아빠입니다.
저는 전산쟁이 9년차이고요.
프로그래밍은 깊게 안들어가봤어요.
저는 저희 아기 사진 블로그를 만들고 싶습니다.
현재 장고를 공부하고 있습니다.
제 포트폴리오는 아래와 같습니다.

3.3.3 Django Basic Tutorial

  1. Django Tutorial GitHub
  2. [Django]Survey WEB Application Tutorial 1
  3. [Django]Survey WEB Application Tutorial 2
  4. [Django]Survey WEB Application Tutorial 3
  5. [Django]Survey WEB Application Tutorial 4
  6. [Django]'polls" is not a registered namespace Error
  7. [Django]Survey WEB Application Tutorial 5
  8. [Django]Survey WEB Application Tutorial 6
  9. [Django]Survey WEB Application Tutorial 7

  1. [Django]Blog Creation Tutorial(Translation/Correction) 1
  2. [Django]Blog Creation Tutorial(Translation/Correction) 2
  3. [Django]Blog Creation Tutorial(Translation/Correction) 3

3.3.4 Basic Setting

  • 가상 환경 설정
python -m venv venv
  • django 설치
pip install django
  • django 버전 확인
python -m django --version

3.3.5 Git

  • gitignore 설정

https://developer-ankiwoong.tistory.com/837

  • git 생성

https://github.com/ankiwoong/python_kindergarten

  • git 연결
git remote add orign https https://github.com/ankiwoong/python_kindergarten.git
git remote -v

3.3.6 Git Commits History

commits URL
Apply .gitignore https://github.com/ankiwoong/python_kindergarten/commit/ff428e41fff8f991c07c02f18487167c3897db72
django-admin startproject anjia . https://github.com/ankiwoong/python_kindergarten/commit/9938507a39755516071f25530a44f67ee432a319
python manage.py startapp blog https://github.com/ankiwoong/python_kindergarten/commit/df9eae3ff65608d536b10cbb84e2160e724b835f
Modify Setting File https://github.com/ankiwoong/python_kindergarten/commit/42d61ff9b3d2dad57973db4d6a85c37c9d41f58a
test img https://github.com/ankiwoong/python_kindergarten/commit/06abf8c0e781966feccfda61553832d36978cdba
delete test https://github.com/ankiwoong/python_kindergarten/commit/150b27ac9e5a07c1aafb9948810071982be294e1
Modify Setting File https://github.com/ankiwoong/python_kindergarten/commit/353d01197fe2278b42372153733f21261b05f223
Modify urls.py(Blog URL & Basic URL handling) https://github.com/ankiwoong/python_kindergarten/commit/e5193d321897f6adf1ebadc018b3b29aacfdf5bb
Index TEST https://github.com/ankiwoong/python_kindergarten/commit/aaf14171863216f1ca165cf3ef6a29d616ffbfc4
Static Processing https://github.com/ankiwoong/python_kindergarten/commit/a18339d7afc861bb97bfb6bcb7acdaf79d4586bd
Colorlib Templates Blogger https://github.com/ankiwoong/python_kindergarten/commit/82097252ab036dd20be7abc50534c4233d8b0cdd
Templates Modify https://github.com/ankiwoong/python_kindergarten/commit/6b00d131c8b733060197fd4c84409c53aade2065
Static Modify https://github.com/ankiwoong/python_kindergarten/commit/764c544c11a7f191b719c3c7ac32b5da7fc6f76b
Static Modify https://github.com/ankiwoong/python_kindergarten/commit/454113160ae32f1377dccdd244cf2a20e29e03dc
Single HTML connection https://github.com/ankiwoong/python_kindergarten/commit/f04f3d9c8363f5b3d0a6d9f1aae1103b48eea0ea
Models Modify https://github.com/ankiwoong/python_kindergarten/commit/b625b9066dc933dc8e5e74ea16bac10e47ef7441
Post Modify https://github.com/ankiwoong/python_kindergarten/commit/dbad39374a276697bad1b15f2b026e4ae4f83f2b
Debugging Django error correction progress https://github.com/ankiwoong/python_kindergarten/commit/511dacb57f229bb539834c23d488350d2c0937fa
Test work after editing featured-image https://github.com/ankiwoong/python_kindergarten/commit/a8af09b08f547f839bc7c51dd3b4ddbfbadc3626
Single page connection https://github.com/ankiwoong/python_kindergarten/commit/d7fb98849e6be773babc77dcf339323764f58cb0
blog modeling work https://github.com/ankiwoong/python_kindergarten/commit/b46d23d0b1c58ab5a23a4d4f7cee82f68a9be2f8
Category / Post on admin page https://github.com/ankiwoong/python_kindergarten/commit/62484893b5ef8a9319e02c7be85598e5aa451881
index modification https://github.com/ankiwoong/python_kindergarten/commit/9f74a0a516457e58916cbc915aa6134c46ddbea7
Edit detail page https://github.com/ankiwoong/python_kindergarten/commit/1fec61bf462a2f1424ea64e5179b954fc1b87dd4
Check the content photos https://github.com/ankiwoong/python_kindergarten/commit/a61126ab52357dcc99509c47c7c4356a1ede7d65
index link operation https://github.com/ankiwoong/python_kindergarten/commit/2ecf2cc672287f81df1c427d6156b1f9d887fb4f
Create writing https://github.com/ankiwoong/python_kindergarten/commit/44cdc23946556d3e14552a554456a4ed64d6aa70
Check for login https://github.com/ankiwoong/python_kindergarten/commit/58014de40c39dcc6bbf369803bf406748ef5dfb7
Write a new post Apply bootstrap https://github.com/ankiwoong/python_kindergarten/commit/fad6ebe0677178722faa04b9165eb7a257af273f
Deduplication https://github.com/ankiwoong/python_kindergarten/commit/5f99739b42be75aa6599504a60564a1b6f38d595
views test https://github.com/ankiwoong/python_kindergarten/commit/9de8288a085265aa8c5d400492d3641e8fc1ab4d
Create README.md https://github.com/ankiwoong/python_kindergarten/commit/b2566d01e711d9948d5d2299568b647c9f279724
Update README.md https://github.com/ankiwoong/python_kindergarten/commit/6a6393cf377dc3564b6cc09f7f83f8dbfde786d6
Apply truncatechars https://github.com/ankiwoong/python_kindergarten/commit/a7e8b66d01266d01a9e3755188833aab3903a992
Admin Page Search ADD https://github.com/ankiwoong/python_kindergarten/commit/4261367349cfb68856c6f1d1120ab65ba8e62f63
Specifies the directory path to find templates https://github.com/ankiwoong/python_kindergarten/commit/c526b96cfb76d98cea134b9659dfa0190cc1d059
Move https://github.com/ankiwoong/python_kindergarten/commit/275adc8ef00288e4c07a919db8f4afa5346671f9
Title Tag Modification https://github.com/ankiwoong/python_kindergarten/commit/fd57e0d19b4a5d90c1f3fb64ab0157e2952db9bc
lang tag korean designation https://github.com/ankiwoong/python_kindergarten/commit/8027fa0b9b218c38f18c6dc424697cd24d128247
Fix https://github.com/ankiwoong/python_kindergarten/commit/bb858002dd3496ae0784de7affefd0ea42cdfa84
Favicon Modify https://github.com/ankiwoong/python_kindergarten/commit/a31997b684dfb57c3a8862d3d5e952f6d6e97d4c
Modify login page(Center alignment) https://github.com/ankiwoong/python_kindergarten/commit/74f132812712c439e06c56613c955e8e1d5a028e
View all posts Paging processing https://github.com/ankiwoong/python_kindergarten/commit/6061d66a0cd1f3c7c9928e63eaf350df08f069f7
loging https://github.com/ankiwoong/python_kindergarten/commit/af5536abdb5ebed460a6b7d216eaa12a9a772c43
video page https://github.com/ankiwoong/python_kindergarten/commit/66b14481a831ea2db07e94320cfcaede901cf44b
admin page https://github.com/ankiwoong/python_kindergarten/commit/e313882c596d60b66d88d4dc9677c152aeaac635
admin page layout https://github.com/ankiwoong/python_kindergarten/commit/a5a565409fa60e0bbabf245f6159688ccc886b84
session add https://github.com/ankiwoong/python_kindergarten/commit/48cf69df151e3b3f2fc28bc990741e9b9ead8cb5
robots.txt add https://github.com/ankiwoong/python_kindergarten/commit/3e9c676da1f708c5864bf7d566bdce51367a62fb
SEO add https://github.com/ankiwoong/python_kindergarten/commit/e987975648ce14d0097a9c85a82e1f5705255a7a
licence add https://github.com/ankiwoong/python_kindergarten/commit/32c5c14e15d24b217bc3807d0e3e84974c15423f
Log add https://github.com/ankiwoong/python_kindergarten/commit/b91ae6e54cccd904321d6edd29e46bdce32ffa53
Login logging (signal) https://github.com/ankiwoong/python_kindergarten/commit/e9ad817ed70adcc1e96560f0bd7e764ccf29ba8f
ALLOWED_HOSTS modify https://github.com/ankiwoong/python_kindergarten/commit/f876480504476fb7128ba6c83440c54203ce0187
HTTP error code handling https://github.com/ankiwoong/python_kindergarten/commit/c7a59927c40472739aa37844acc330c97259e0bb

3.3.7 Project Code Review

  • 프로젝트 생성
django-admin startproject anjia .
  • runserver 테스트
python manage.py runserver
  • App 생성
python manage.py startapp blog
  • anjia > settings.py
ALLOWED_HOSTS = ['*']                      # 루트 URL

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

INSTALLED_APPS += [
    'blog.apps.BlogConfig',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

LANGUAGE_CODE = 'ko-kr'         # 언어 : 한국

TIME_ZONE = 'Asia/Seoul'        # 타임존 : 한국 시간(기본 : UTC(세계표준시))
  • 데이터베이스에 변경 필요 사항 추출
python manage.py makemigrations
  • 데이터베이스에 변경사항 반영
python manage.py migrate
  • 관리자 생성
python manage.py createsuperuser
  • Admin 확인
http://127.0.0.1:8000/admin/
  • anjia > urls.py
"""anjia URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from django.views.generic import RedirectView
from django.conf import settings
from django.conf.urls.static import static


# http://localhost:8000/ => http://localhost:8000/blog
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
    path('', RedirectView.as_view(url='/blog/', permanent=True)),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)     # staic 정적 파일 처리
  • blog > urls.py
from django.urls import path
from blog import views

# url 처리규칙
urlpatterns = [
    path('', views.index, name='index'),
]
  • blog > views.py
from django.shortcuts import render

# Create your views here.


def index(req):
    context = {

    }

    return render(req, 'index.html', context=context)
  • templates > index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>TEST BLOG</title>
  </head>
  <body>
    <h1>Hello My TEST BLOG</h1>
  </body>
</html>
  • anjia > settings.py
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static/'),
)
  • Bootstrap

https://colorlib.com/wp/free-bootstrap-blog-templates/

  • templates > index.html
index.html
<!DOCTYPE HTML>
<html lang="en-US">
    <head>
        <title>Suppablog - Minimal Blog Html Template</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="description" content="Template by Colorlib" />
        <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
        <meta name="author" content="Colorlib" />
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

        <link rel="shortcut icon" href="images/favicon.png" />
        <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700' rel='stylesheet' type='text/css'>
        <link rel="stylesheet" type="text/css"  href='css/clear.css' />
        <link rel="stylesheet" type="text/css"  href='css/common.css' />
        <link rel="stylesheet" type="text/css"  href='css/font-awesome.min.css' />
        <link rel="stylesheet" type="text/css"  href='css/carouFredSel.css' />
        <link rel="stylesheet" type="text/css"  href='css/sm-clean.css' />
        <link rel="stylesheet" type="text/css"  href='style.css' />

        <!--[if lt IE 9]>
                <script src="js/html5.js"></script>
        <![endif]-->

    </head>


    <body class="home blog">

        <!-- Preloader Gif -->
        <table class="doc-loader">
            <tbody>
                <tr>
                    <td>
                        <img src="images/ajax-document-loader.gif" alt="Loading...">
                    </td>
                </tr>
            </tbody>
        </table>

        <!-- Left Sidebar -->
        <div id="sidebar" class="sidebar">
            <div class="menu-left-part">
                <div class="search-holder">
                    <label>
                        <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s" title="Search for:">
                    </label>
                </div>
                <div class="site-info-holder">
                    <h1 class="site-title">Suppablog</h1>
                    <p class="site-description">
                        Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                    </p>
                </div>
                <nav id="header-main-menu">
                    <ul class="main-menu sm sm-clean">
                        <li><a href="index.html" class="current">Home</a></li>
                        <li><a href="about.html">About</a></li>
                        <li><a href="scroll.html">Scroll</a></li>
                        <li><a href="contact.html">Contact</a></li>
                    </ul>
                </nav>
                <footer>
                    <div class="footer-info">
                        ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a href="https://colorlib.com">COLORLIB</a>.
                    </div>
                </footer>
            </div>
            <div class="menu-right-part">
                <div class="logo-holder">
                    <a href="index.html">
                        <img src="images/logo.png" alt="Suppablog WP">
                    </a>
                </div>
                <div class="toggle-holder">
                    <div id="toggle">
                        <div class="menu-line"></div>
                    </div>
                </div>
                <div class="social-holder">
                    <div class="social-list">
                        <a href="#"><i class="fa fa-twitter"></i></a>
                        <a href="#"><i class="fa fa-youtube-play"></i></a>
                        <a href="#"><i class="fa fa-facebook"></i></a>
                        <a href="#"><i class="fa fa-vimeo"></i></a>
                        <a href="#"><i class="fa fa-behance"></i></a>
                        <a href="#"><i class="fa fa-rss"></i></a>
                    </div>
                </div>
                <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
            </div>
            <div class="clear"></div>
        </div>

        <!-- Home Content -->
        <div id="content" class="site-content">
            <div id="blog-wrapper">
                <div class="blog-holder center-relative">


                    <article id="post-1" class="blog-item-holder featured-post">
                        <div class="entry-content relative">
                            <div class="content-1170 center-relative">
                                <div class="cat-links">
                                    <ul>
                                        <li>
                                            <a href="#">Crafting</a>
                                        </li>
                                    </ul>
                                </div>
                                <div class="entry-date published">February 12, 2016</div>
                                <h2 class="entry-title">
                                    <a href="single.html">Whatever is begun in anger ends in shame</a>
                                </h2>
                                <div class="excerpt">
                                    Now when I had mastered the language of this water and had come to know every trifling feature that bordered the great river as familiarly as I knew the letters of the alphabet, I had made a valuable acquisition. I still keep in mind a certain wonderful sunset which I witnessed when and steamboating<a class="read-more" href="single.html"></a>
                                </div>
                                <div class="clear"></div>
                            </div>
                        </div>
                    </article>


                    <article id="post-2" class="blog-item-holder">
                        <div class="entry-content relative">
                            <div class="content-1170 center-relative">
                                <h2 class="entry-title">
                                    <a href="single.html">I like to reinvent myself</a>
                                </h2>
                                <div class="cat-links">
                                    <ul>
                                        <li>
                                            <a href="#">Science</a>
                                        </li>
                                    </ul>
                                </div>
                                <div class="entry-date published">February 12, 2016</div>
                                <div class="clear"></div>
                            </div>
                        </div>
                    </article>


                    <article id="post-3" class="blog-item-holder">
                        <div class="entry-content relative">
                            <div class="content-1170 center-relative">
                                <h2 class="entry-title">
                                    <a href="single.html">Everything is design</a>
                                </h2>
                                <div class="cat-links">
                                    <ul>
                                        <li>
                                            <a href="#">Art</a>
                                        </li>
                                    </ul>
                                </div>
                                <div class="entry-date published">February 12, 2016</div>
                                <div class="clear"></div>
                            </div>
                        </div>
                    </article>



                    <article id="post-4" class="blog-item-holder">
                        <div class="entry-content relative">
                            <div class="content-1170 center-relative">
                                <h2 class="entry-title">
                                    <a href="single.html">It’s all about experience</a>
                                </h2>
                                <div class="cat-links">
                                    <ul>
                                        <li>
                                            <a href="#">Life</a>
                                        </li>
                                    </ul>
                                </div>
                                <div class="entry-date published">February 12, 2016</div>
                                <div class="clear"></div>
                            </div>
                        </div>
                    </article>



                    <article id="post-5" class="blog-item-holder">
                        <div class="entry-content relative">
                            <div class="content-1170 center-relative">
                                <h2 class="entry-title">
                                    <a href="single.html">This is not my code</a>
                                </h2>
                                <div class="cat-links">
                                    <ul>
                                        <li>
                                            <a href="#">Coding</a>
                                        </li>
                                    </ul>
                                </div>
                                <div class="entry-date published">February 12, 2016</div>
                                <div class="clear"></div>
                            </div>
                        </div>
                    </article>



                    <article id="post-6" class="blog-item-holder">
                        <div class="entry-content relative">
                            <div class="content-1170 center-relative">
                                <h2 class="entry-title">
                                    <a href="single.html">Support human activity</a>
                                </h2>
                                <div class="cat-links">
                                    <ul>
                                        <li>
                                            <a href="#">Advocacy</a>
                                        </li>
                                    </ul>
                                </div>
                                <div class="entry-date published">February 12, 2016</div>
                                <div class="clear"></div>
                            </div>
                        </div>
                    </article>

                </div>
                <div class="clear"></div>
                <div class="block load-more-holder">LOAD MORE ENTRIES</div>
            </div>

            <div class="featured-image-holder">
                <div class="featured-post-image" style="background-image: url(demo-images/featured-image.jpg)"></div>

            </div>
            <div class="clear"></div>
        </div>



        <!--Load JavaScript-->
        <script type="text/javascript" src="js/jquery.js"></script>
        <script type='text/javascript' src='js/imagesloaded.pkgd.js'></script>
        <script type='text/javascript' src='js/jquery.nicescroll.min.js'></script>
        <script type='text/javascript' src='js/jquery.smartmenus.min.js'></script>
        <script type='text/javascript' src='js/jquery.carouFredSel-6.0.0-packed.js'></script>
        <script type='text/javascript' src='js/jquery.mousewheel.min.js'></script>
        <script type='text/javascript' src='js/jquery.touchSwipe.min.js'></script>
        <script type='text/javascript' src='js/jquery.easing.1.3.js'></script>
        <script type='text/javascript' src='js/main.js'></script>
    </body>
</html>
  • templates > single.html
single.html
<!DOCTYPE HTML>
<html lang="en-US">
    <head>
        <title>Suppablog - Minimal Blog Html Template</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="description" content="Template by Colorlib" />
        <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
        <meta name="author" content="Colorlib" />
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

        <link rel="shortcut icon" href="images/favicon.png" />
        <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700' rel='stylesheet' type='text/css'>
        <link rel="stylesheet" type="text/css"  href='css/clear.css' />
        <link rel="stylesheet" type="text/css"  href='css/common.css' />
        <link rel="stylesheet" type="text/css"  href='css/font-awesome.min.css' />
        <link rel="stylesheet" type="text/css"  href='css/carouFredSel.css' />
        <link rel="stylesheet" type="text/css"  href='css/sm-clean.css' />
        <link rel="stylesheet" type="text/css"  href='style.css' />

        <!--[if lt IE 9]>
                <script src="js/html5.js"></script>
        <![endif]-->

    </head>


    <body class="single-post">

        <!-- Preloader Gif -->
        <table class="doc-loader">
            <tbody>
                <tr>
                    <td>
                        <img src="images/ajax-document-loader.gif" alt="Loading...">
                    </td>
                </tr>
            </tbody>
        </table>

        <!-- Left Sidebar -->
        <div id="sidebar" class="sidebar">
            <div class="menu-left-part">
                <div class="search-holder">
                    <label>
                        <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s" title="Search for:">
                    </label>
                </div>
                <div class="site-info-holder">
                    <div class="site-title">Suppablog</div>
                    <p class="site-description">
                        Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                    </p>
                </div>
                <nav id="header-main-menu">
                    <ul class="main-menu sm sm-clean">
                        <li><a href="index.html" class="current">Home</a></li>
                        <li><a href="about.html">About</a></li>
                        <li><a href="scroll.html">Scroll</a></li>
                        <li><a href="contact.html">Contact</a></li>
                    </ul>
                </nav>
                <footer>
                    <div class="footer-info">
                        ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a href="https://colorlib.com">COLORLIB</a>.
                    </div>
                </footer>
            </div>
            <div class="menu-right-part">
                <div class="logo-holder">
                    <a href="index.html">
                        <img src="images/logo.png" alt="Suppablog WP">
                    </a>
                </div>
                <div class="toggle-holder">
                    <div id="toggle">
                        <div class="menu-line"></div>
                    </div>
                </div>
                <div class="social-holder">
                    <div class="social-list">
                        <a href="#"><i class="fa fa-twitter"></i></a>
                        <a href="#"><i class="fa fa-youtube-play"></i></a>
                        <a href="#"><i class="fa fa-facebook"></i></a>
                        <a href="#"><i class="fa fa-vimeo"></i></a>
                        <a href="#"><i class="fa fa-behance"></i></a>
                        <a href="#"><i class="fa fa-rss"></i></a>
                    </div>
                </div>
                <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
            </div>
            <div class="clear"></div>
        </div>

        <!-- Single Content -->
        <div id="content" class="site-content center-relative">
            <div class="single-post-wrapper content-1070 center-relative">

                <article class="center-relative">
                    <h1 class="entry-title">
                        I like to reinvent myself
                    </h1>
                    <div class="post-info content-660 center-relative">
                        <div class="cat-links">
                            <ul>
                                <li><a href="#">Science</a></li>
                            </ul>
                        </div>
                        <div class="entry-date published">February 12, 2016</div>
                        <div class="clear"></div>
                    </div>

                    <div class="entry-content">
                        <div class="content-wrap content-660 center-relative">
                            <p>Now when I had mastered the language of this water and had come to know every trifling feature that bordered the great river as familiarly as I knew the letters of the alphabet, I had made a valuable acquisition.</p>
                            <br>
                            <div class="clear"></div>
                        </div>
                        <div class="post-full-width">
                            <script>
                                var slider1_speed = "500";
                                var slider1_auto = "true";
                                var slider1_pagination = "true";
                                var slider1_hover = "true";
                            </script>
                            <div class="image-slider-wrapper">
                                <div class="caroufredsel_wrapper">
                                    <ul id="slider1" class="image-slider slides center-text">
                                        <li><img src="demo-images/01_blogpost_galery.jpg" alt=""></li>
                                        <li><img src="demo-images/02_blogpost_galery.jpg" alt=""></li>
                                        <li><img src="demo-images/03_blogpost_galery.jpg" alt=""></li>
                                    </ul>
                                </div>
                                <div class="slider1_pagination carousel_pagination left"></div>
                                <div class="clear"></div>
                            </div>
                            <div class="clear"></div>
                        </div>
                        <div class="content-wrap content-660 center-relative ">
                            <p>I still keep in mind a certain wonderful sunset which I witnessed when and steamboating was new to me. A broad expanse of the river was turned too blood in the middle distance the red hue brightened into gold, through which a solitary log came floating, black and conspicuous in one place a long calm slanting mark lay sparkling upon the water in another the surface was broken by boiling, tumbling rings, that were as many-tinted as an opal where the ruddy flush was faintest, was a smooth spot that was covered with graceful circles and radiating lines.</p>
                            <br>
                            <p class="wrap-blockquote">Ever so delicately traced the shore on our left was densely wooded, and the som ber shadow that fell from this forest was broken in one place by a long, ruffled trail that shone like silver and high above the forest wall.</p>
                            <blockquote class="inline-blockquote">
                                <p>There were graceful curves, reflected images, woody on the heights, soft distances and over the whole scene far and so near, the dissolving lights drifted steadily now dissolving lights.</p>
                            </blockquote>
                            <p class="wrap-blockquote">But as I have said, a day came when I began to cease from noting the glories and the charms which the moon and the sun and the twilight wrought upon the river’s face another day came when I ceased altogether to note them. Then, if that sunset scene had been repeated, I should have looked upon it without rapture, and should have commented upon it, inwardly, after this fashion. But as I have said, a day came when I began to cease from noting the glories and the charms which the moon and the sun and the twilight wrought upon the one graceful curves, reflected images, woody heights, soft distances and over the whole sun scene, far and near, the dissolving lights drifted steadily, enriching it, every passing the moment, with new marvels of coloring. The world was new to me, and I had never seen anything like this at home. But as I have said, a day came when I began to cease from noting the glories and the charms which the moon and the sun and the twilight wrought upon the river’s face another day came when I ceased altogether to note them. Then, if that sunset scene had been repeated, I should have looked upon it without rapture, and should have commented upon it, inwardly, after this fashion.</p>
                            <br>
                            <br>
                            <img src="demo-images/one_drop_post_image02.jpg" alt="">
                            <br>
                            <br>
                            <p>Duis iaculis mattis rutrum. Sed iaculis magna sit amet suscipit ornare. Nulla ornare leo a tortor aliquam, quis interdum ex tempor. Quisque ultricies consequat suscipit. Donec tincidunt tempor ornare. Praesent a enim vel augue suscipit auctor in gravida augue. Suspendisse ut libero sit amet augue molestie fringilla. Fusce molestie, velit a finibus eleifend, nibh odio sagittis est, id aliquet turpis orci quis nibh.</p>
                        </div>
                    </div>
                    <div class="clear"></div>
                </article>
            </div>
        </div>



        <!--Load JavaScript-->
        <script type="text/javascript" src="js/jquery.js"></script>
        <script type='text/javascript' src='js/imagesloaded.pkgd.js'></script>
        <script type='text/javascript' src='js/jquery.nicescroll.min.js'></script>
        <script type='text/javascript' src='js/jquery.smartmenus.min.js'></script>
        <script type='text/javascript' src='js/jquery.carouFredSel-6.0.0-packed.js'></script>
        <script type='text/javascript' src='js/jquery.mousewheel.min.js'></script>
        <script type='text/javascript' src='js/jquery.touchSwipe.min.js'></script>
        <script type='text/javascript' src='js/jquery.easing.1.3.js'></script>
        <script type='text/javascript' src='js/main.js'></script>
    </body>
</html>
  • index.html static 수정 작업
index.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <!-- static 사용을 위한 명령어 -->
    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="home blog">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <h1 class="site-title">Suppablog</h1>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="index.html" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="index.html">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Home Content -->
    <div id="content" class="site-content">
        <div id="blog-wrapper">
            <div class="blog-holder center-relative">


                <article id="post-1" class="blog-item-holder featured-post">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">Crafting</a>
                                    </li>
                                </ul>
                            </div>
                            <div class="entry-date published">February 12, 2016</div>
                            <h2 class="entry-title">
                                <a href="single.html">Whatever is begun in anger ends in shame</a>
                            </h2>
                            <div class="excerpt">
                                Now when I had mastered the language of this water and had come to know every trifling
                                feature that bordered the great river as familiarly as I knew the letters of the
                                alphabet, I had made a valuable acquisition. I still keep in mind a certain wonderful
                                sunset which I witnessed when and steamboating<a class="read-more"
                                    href="single.html"></a>
                            </div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>


                <article id="post-2" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <a href="single.html">I like to reinvent myself</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">Science</a>
                                    </li>
                                </ul>
                            </div>
                            <div class="entry-date published">February 12, 2016</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>


                <article id="post-3" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <a href="single.html">Everything is design</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">Art</a>
                                    </li>
                                </ul>
                            </div>
                            <div class="entry-date published">February 12, 2016</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>



                <article id="post-4" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <a href="single.html">It’s all about experience</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">Life</a>
                                    </li>
                                </ul>
                            </div>
                            <div class="entry-date published">February 12, 2016</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>



                <article id="post-5" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <a href="single.html">This is not my code</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">Coding</a>
                                    </li>
                                </ul>
                            </div>
                            <div class="entry-date published">February 12, 2016</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>



                <article id="post-6" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <a href="single.html">Support human activity</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">Advocacy</a>
                                    </li>
                                </ul>
                            </div>
                            <div class="entry-date published">February 12, 2016</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>

            </div>
            <div class="clear"></div>
            <div class="block load-more-holder">LOAD MORE ENTRIES</div>
        </div>

        <div class="featured-image-holder">
            <div class="featured-post-image"
                style="background-image: url({% static 'demo-images/featured-image.jpg' %})"></div>

        </div>
        <div class="clear"></div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>
  • single.html static 수정 작업
single.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="single-post">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <div class="site-title">Suppablog</div>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="index.html" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="index.html">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Single Content -->
    <div id="content" class="site-content center-relative">
        <div class="single-post-wrapper content-1070 center-relative">

            <article class="center-relative">
                <h1 class="entry-title">
                    I like to reinvent myself
                </h1>
                <div class="post-info content-660 center-relative">
                    <div class="cat-links">
                        <ul>
                            <li><a href="#">Science</a></li>
                        </ul>
                    </div>
                    <div class="entry-date published">February 12, 2016</div>
                    <div class="clear"></div>
                </div>

                <div class="entry-content">
                    <div class="content-wrap content-660 center-relative">
                        <p>Now when I had mastered the language of this water and had come to know every trifling
                            feature that bordered the great river as familiarly as I knew the letters of the alphabet, I
                            had made a valuable acquisition.</p>
                        <br>
                        <div class="clear"></div>
                    </div>
                    <div class="post-full-width">
                        <script>
                            var slider1_speed = "500";
                            var slider1_auto = "true";
                            var slider1_pagination = "true";
                            var slider1_hover = "true";
                        </script>
                        <div class="image-slider-wrapper">
                            <div class="caroufredsel_wrapper">
                                <ul id="slider1" class="image-slider slides center-text">
                                    <li><img src="{% static 'demo-images/01_blogpost_galery.jpg' %}" alt=""></li>
                                    <li><img src="{% static 'demo-images/02_blogpost_galery.jpg' %}" alt=""></li>
                                    <li><img src="{% static 'demo-images/03_blogpost_galery.jpg' %}" alt=""></li>
                                </ul>
                            </div>
                            <div class="slider1_pagination carousel_pagination left"></div>
                            <div class="clear"></div>
                        </div>
                        <div class="clear"></div>
                    </div>
                    <div class="content-wrap content-660 center-relative ">
                        <p>I still keep in mind a certain wonderful sunset which I witnessed when and steamboating was
                            new to me. A broad expanse of the river was turned too blood in the middle distance the red
                            hue brightened into gold, through which a solitary log came floating, black and conspicuous
                            in one place a long calm slanting mark lay sparkling upon the water in another the surface
                            was broken by boiling, tumbling rings, that were as many-tinted as an opal where the ruddy
                            flush was faintest, was a smooth spot that was covered with graceful circles and radiating
                            lines.</p>
                        <br>
                        <p class="wrap-blockquote">Ever so delicately traced the shore on our left was densely wooded,
                            and the som ber shadow that fell from this forest was broken in one place by a long, ruffled
                            trail that shone like silver and high above the forest wall.</p>
                        <blockquote class="inline-blockquote">
                            <p>There were graceful curves, reflected images, woody on the heights, soft distances and
                                over the whole scene far and so near, the dissolving lights drifted steadily now
                                dissolving lights.</p>
                        </blockquote>
                        <p class="wrap-blockquote">But as I have said, a day came when I began to cease from noting the
                            glories and the charms which the moon and the sun and the twilight wrought upon the river’s
                            face another day came when I ceased altogether to note them. Then, if that sunset scene had
                            been repeated, I should have looked upon it without rapture, and should have commented upon
                            it, inwardly, after this fashion. But as I have said, a day came when I began to cease from
                            noting the glories and the charms which the moon and the sun and the twilight wrought upon
                            the one graceful curves, reflected images, woody heights, soft distances and over the whole
                            sun scene, far and near, the dissolving lights drifted steadily, enriching it, every passing
                            the moment, with new marvels of coloring. The world was new to me, and I had never seen
                            anything like this at home. But as I have said, a day came when I began to cease from noting
                            the glories and the charms which the moon and the sun and the twilight wrought upon the
                            river’s face another day came when I ceased altogether to note them. Then, if that sunset
                            scene had been repeated, I should have looked upon it without rapture, and should have
                            commented upon it, inwardly, after this fashion.</p>
                        <br>
                        <br>
                        <img src="{% static 'demo-images/one_drop_post_image02.jpg' %}" alt="">
                        <br>
                        <br>
                        <p>Duis iaculis mattis rutrum. Sed iaculis magna sit amet suscipit ornare. Nulla ornare leo a
                            tortor aliquam, quis interdum ex tempor. Quisque ultricies consequat suscipit. Donec
                            tincidunt tempor ornare. Praesent a enim vel augue suscipit auctor in gravida augue.
                            Suspendisse ut libero sit amet augue molestie fringilla. Fusce molestie, velit a finibus
                            eleifend, nibh odio sagittis est, id aliquet turpis orci quis nibh.</p>
                    </div>
                </div>
                <div class="clear"></div>
            </article>
        </div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>
  • style.css 경로 수정 작업
.read-more {
  background-image: url("../images/arrow.png");
  width: 30px;
  height: 30px;
  background-size: 30px;
  background-repeat: no-repeat;
  display: inline-block;
  vertical-align: -11px;
  margin-left: 15px;
}


  • featured-image 기본 이미지 확인
  • featured-image 수정 이미지
  • featured-image 수정 후 테스트 작업
  • 상세 페이지 연결 작업

blog > urls.py

from django.urls import path
from blog import views

# url 처리규칙
urlpatterns = [
    path('', views.index, name='index'),
    path('single/', views.single, name='single'),
]

blog > views.py

from django.shortcuts import render

# Create your views here.


def index(req):
    context = {

    }

    return render(req, 'index.html', context=context)


def single(req):
    context = {

    }

    return render(req, 'single.html', context=context)
  • blog 모델링 작업

blog > models.py

from django.db import models
from django.urls import reverse


# 블로그 카테고리
class Category(models.Model):
    name = models.CharField(max_length=50, help_text='블로그 카테고리')

    def __str__(self):
        return self.name


# 블로그 글(제목, 작성일, 대표 이미지, 내용, 분류)
class Post(models.Model):
    title = models.CharField(max_length=200)
    title_image = models.ImageField(blank=True)
    content = models. TextField()
    createDate = models.DateTimeField(auto_now_add=True)
    updateDate = models.DateTimeField(auto_now_add=True)
    category = models.ManyToManyField(Category, help_text='블로그 카테고리')

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('single', args=[str(self.id)])

anjia > settings.py

# 미디어 파일 처리
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

anjia > urls.py

"""anjia URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from django.views.generic import RedirectView
from django.conf import settings
from django.conf.urls.static import static


# http://localhost:8000/ => http://localhost:8000/blog
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
    path('', RedirectView.as_view(url='/blog/', permanent=True)),
]

urlpatterns += static(settings.STATIC_URL,
                      document_root=settings.STATIC_ROOT)     # staic 정적 파일 처리
urlpatterns += static(settings.MEDIA_URL,
                      document_root=settings.MEDIA_ROOT)     # media 정적 파일 처리

makemigrations 작업

python manage.py makemigrations

migrate 작업

python manage.py migrate
  • admin 페이지에 모델 표시

blog > admin.py

from django.contrib import admin
from blog.models import Category, Post

admin.site.register(Category)
admin.site.register(Post)
  • index 작업

blog > views.py

from django.shortcuts import render

from blog.models import Category, Post

# Create your views here.


def index(req):
    post_latest = Post.objects.order_by("-createDate")[:6]      # 내림차순
    context = {
        "post_latest": post_latest
    }

    return render(req, 'index.html', context=context)


def single(req):
    context = {

    }

    return render(req, 'single.html', context=context)

blogs > models.py

from django.db import models
from django.urls import reverse


# 카테고리
class Category(models.Model):
    name = models.CharField(max_length=50, help_text='카테고리')

    def __str__(self):
        return self.name


# 블로그 글(제목, 작성일, 대표 이미지, 내용, 분류)
class Post(models.Model):
    title = models.CharField(max_length=200)
    title_image = models.ImageField(blank=True)
    content = models. TextField()
    createDate = models.DateTimeField(auto_now_add=True)
    updateDate = models.DateTimeField(auto_now_add=True)
    category = models.ManyToManyField(Category, help_text='카테고리')

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('single', args=[str(self.id)])

    # 300자가 넘을경우
    def is_content_more300(self):
        return len(self.content) > 300

    # 300자가 안넘을경우
    def get_content_under300(self):
        return self.content[:300]
  • 본문 내용 수정
{% for post in post_latest %}
                <!-- 첫번째 글 처리 -->
                {% if forloop.first %}
                <article id="post-1" class="blog-item-holder featured-post">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">
                                            <!-- 카테고리 -->
                                            {% for c in post.category.all %}
                                            {{ c }}
                                            <!-- 카테고리가 여러개인 경우 , 표시 -->
                                            {% if not forloop.last %}
                                            ,
                                            {% endif %}
                                            {% endfor %}
                                        </a>
                                    </li>
                                </ul>
                            </div>
                            <!-- 글 작성일 -->
                            <div class="entry-date published">{{ post.createDate }}</div>
                            <h2 class="entry-title">
                                <!-- 글 제목 -->
                                <a href="{% url 'single' %}">{{ post.title }}</a>
                            </h2>
                            <div class="excerpt">
                                <!-- 글 내용 300자 체크 -->
                                {% if post.is_content_more300 %}
                                <!-- 300자가 안넘을경우 -->
                                {{ post.get_content_under300 }}
                                {% else %}
                                {{ post.conetent }}
                                {% endif %}
                                <a class="read-more" href="{% url 'single' %}"></a>
                            </div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>
                <!-- 두번째 글 부터 -->
                {% else %}
                <article id="post-{{ forloop.counter }}" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <!-- 글 제목 -->
                                <a href="{% url 'single' %}">{{ post.title }}</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <!-- 카테고리 -->
                                        <a href="#">
                                            {% for c in post.category.all %}
                                            {{ c }}
                                            <!-- 카테고리가 여러개인 경우 , 표시 -->
                                            {% if not forloop.last %}
                                            ,
                                            {% endif %}
                                            {% endfor %}
                                        </a>
                                    </li>
                                </ul>
                            </div>
                            <!-- 글 작성일 -->
                            <div class="entry-date published">{{ post.createDate }}</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>
                {% endif %}
                {% endfor %}
  • 상세 페이지 수정 작업

blog > views.py

from django.shortcuts import render
from django.views import generic

from blog.models import Category, Post

# Create your views here.


def index(req):
    post_latest = Post.objects.order_by("-createDate")[:6]      # 내림차순
    context = {
        "post_latest": post_latest
    }

    return render(req, 'index.html', context=context)


class PostDetailView(generic.DetailView):
    model = Post

blog > models.py

from django.db import models
from django.urls import reverse


# 카테고리
class Category(models.Model):
    name = models.CharField(max_length=50, help_text='카테고리')

    def __str__(self):
        return self.name


# 블로그 글(제목, 작성일, 대표 이미지, 내용, 분류)
class Post(models.Model):
    title = models.CharField(max_length=200)
    title_image = models.ImageField(blank=True)
    content = models. TextField()
    createDate = models.DateTimeField(auto_now_add=True)
    updateDate = models.DateTimeField(auto_now_add=True)
    category = models.ManyToManyField(Category, help_text='카테고리')

    def __str__(self):
        return self.title

    # 1번 글 -> post/1
    def get_absolute_url(self):
        return reverse('post', args=[str(self.id)])

    # 300자가 넘을경우
    def is_content_more300(self):
        return len(self.content) > 300

    # 300자가 안넘을경우
    def get_content_under300(self):
        return self.content[:300]

index.html 수정

index.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <!-- static 사용을 위한 명령어 -->
    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="home blog">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <h1 class="site-title">Suppablog</h1>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="index.html" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="index.html">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Home Content -->
    <div id="content" class="site-content">
        <div id="blog-wrapper">
            <div class="blog-holder center-relative">
                {% for post in post_latest %}
                <!-- 첫번째 글 처리 -->
                {% if forloop.first %}
                <article id="post-1" class="blog-item-holder featured-post">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">
                                            <!-- 카테고리 -->
                                            {% for c in post.category.all %}
                                            {{ c }}
                                            <!-- 카테고리가 여러개인 경우 , 표시 -->
                                            {% if not forloop.last %}
                                            ,
                                            {% endif %}
                                            {% endfor %}
                                        </a>
                                    </li>
                                </ul>
                            </div>
                            <!-- 글 작성일 -->
                            <div class="entry-date published">{{ post.createDate }}</div>
                            <h2 class="entry-title">
                                <!-- 글 제목 -->
                                <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                            </h2>
                            <div class="excerpt">
                                <!-- 글 내용 300자 체크 -->
                                {% if post.is_content_more300 %}
                                <!-- 300자가 안넘을경우 -->
                                {{ post.get_content_under300 }}
                                {% else %}
                                {{ post.content }}
                                {% endif %}
                                <a class="read-more" href="{{ post.get_absolute_url }}"></a>
                            </div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>
                <!-- 두번째 글 부터 -->
                {% else %}
                <article id="post-{{ forloop.counter }}" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <!-- 글 제목 -->
                                <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <!-- 카테고리 -->
                                        <a href="#">
                                            {% for c in post.category.all %}
                                            {{ c }}
                                            <!-- 카테고리가 여러개인 경우 , 표시 -->
                                            {% if not forloop.last %}
                                            ,
                                            {% endif %}
                                            {% endfor %}
                                        </a>
                                    </li>
                                </ul>
                            </div>
                            <!-- 글 작성일 -->
                            <div class="entry-date published">{{ post.createDate }}</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>
                {% endif %}
                {% endfor %}
            </div>
            <div class="clear"></div>
            <div class="block load-more-holder">LOAD MORE ENTRIES</div>
        </div>

        <div class="featured-image-holder">
            <div class="featured-post-image"
                style="background-image: url({% static 'demo-images/featured-image.jpg' %})"></div>

        </div>
        <div class="clear"></div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>

single.html 이름 변경 및 폴더 구조 변경 작업
├─anjia
│ └─__pycache__
├─blog
│ ├─migrations
│ │ └─__pycache__
│ ├─templates
│ │ └─blog
│ └─__pycache__
├─media
├─static
│ ├─css
│ ├─demo-images
│ ├─fonts
│ ├─images
│ └─js

post_detail,html 수정 작업

post_detail,html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="single-post">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <div class="site-title">Suppablog</div>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="index.html" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="index.html">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Single Content -->
    <div id="content" class="site-content center-relative">
        <div class="single-post-wrapper content-1070 center-relative">

            <article class="center-relative">
                <h1 class="entry-title">
                    <!-- 글제목 -->
                    {{ post.title }}
                </h1>
                <div class="post-info content-660 center-relative">
                    <div class="cat-links">
                        <ul>
                            <li><a href="#">
                                    <!-- 카테고리 -->
                                    {% for c in post.category.all %}
                                    {{ c }}
                                    <!-- 카테고리가 여러개인 경우 , 표시 -->
                                    {% if not forloop.last %}
                                    ,
                                    {% endif %}
                                    {% endfor %}
                                </a></li>
                        </ul>
                    </div>
                    <!-- 글 작성일 -->
                    <div class="entry-date published">{{ post.createDate }}</div>
                    <div class="clear"></div>
                </div>

                <div class="entry-content">
                    <div class="content-wrap content-660 center-relative">
                        <!-- 글 내용 -->
                        {{ post.content }}
                        <div class="clear"></div>
                    </div>
                </div>
                <div class="clear"></div>
            </article>
        </div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>
  • 글 내용 중 사진 유무 확인 후 표시

post_detail.html

post_detail.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="single-post">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <div class="site-title">Suppablog</div>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="index.html" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="index.html">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Single Content -->
    <div id="content" class="site-content center-relative">
        <div class="single-post-wrapper content-1070 center-relative">

            <article class="center-relative">
                <h1 class="entry-title">
                    <!-- 글제목 -->
                    {{ post.title }}
                </h1>
                <div class="post-info content-660 center-relative">
                    <div class="cat-links">
                        <ul>
                            <li><a href="#">
                                    <!-- 카테고리 -->
                                    {% for c in post.category.all %}
                                    {{ c }}
                                    <!-- 카테고리가 여러개인 경우 , 표시 -->
                                    {% if not forloop.last %}
                                    ,
                                    {% endif %}
                                    {% endfor %}
                                </a></li>
                        </ul>
                    </div>
                    <!-- 글 작성일 -->
                    <div class="entry-date published">{{ post.createDate }}</div>
                    <div class="clear"></div>
                </div>

                <!-- 사진 -->
                {% if post.title_image %}
                <div class="post-full-width">
                    <img src="{{ post.title_image.url }}" alt="">
                </div>
                {% endif %}

                <div class=" entry-content">
                    <div class="content-wrap content-660 center-relative">
                        <!-- 글 내용 -->
                        {{ post.content }}
                        <div class="clear"></div>
                    </div>
                </div>
                <div class="clear"></div>
            </article>
        </div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>
  • index 페이지 연결 작업

index.html

index.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <!-- static 사용을 위한 명령어 -->
    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="home blog">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <h1 class="site-title">Suppablog</h1>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Home Content -->
    <div id="content" class="site-content">
        <div id="blog-wrapper">
            <div class="blog-holder center-relative">
                {% for post in post_latest %}
                <!-- 첫번째 글 처리 -->
                {% if forloop.first %}
                <article id="post-1" class="blog-item-holder featured-post">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">
                                            <!-- 카테고리 -->
                                            {% for c in post.category.all %}
                                            {{ c }}
                                            <!-- 카테고리가 여러개인 경우 , 표시 -->
                                            {% if not forloop.last %}
                                            ,
                                            {% endif %}
                                            {% endfor %}
                                        </a>
                                    </li>
                                </ul>
                            </div>
                            <!-- 글 작성일 -->
                            <div class="entry-date published">{{ post.createDate }}</div>
                            <h2 class="entry-title">
                                <!-- 글 제목 -->
                                <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                            </h2>
                            <div class="excerpt">
                                <!-- 글 내용 300자 체크 -->
                                {% if post.is_content_more300 %}
                                <!-- 300자가 안넘을경우 -->
                                {{ post.get_content_under300 }}
                                {% else %}
                                {{ post.content }}
                                {% endif %}
                                <a class="read-more" href="{{ post.get_absolute_url }}"></a>
                            </div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>
                <!-- 두번째 글 부터 -->
                {% else %}
                <article id="post-{{ forloop.counter }}" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <!-- 글 제목 -->
                                <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <!-- 카테고리 -->
                                        <a href="#">
                                            {% for c in post.category.all %}
                                            {{ c }}
                                            <!-- 카테고리가 여러개인 경우 , 표시 -->
                                            {% if not forloop.last %}
                                            ,
                                            {% endif %}
                                            {% endfor %}
                                        </a>
                                    </li>
                                </ul>
                            </div>
                            <!-- 글 작성일 -->
                            <div class="entry-date published">{{ post.createDate }}</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>
                {% endif %}
                {% endfor %}
            </div>
            <div class="clear"></div>
            <div class="block load-more-holder">LOAD MORE ENTRIES</div>
        </div>

        <div class="featured-image-holder">
            <div class="featured-post-image"
                style="background-image: url({% static 'demo-images/featured-image.jpg' %})"></div>

        </div>
        <div class="clear"></div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>

post_detail.html

post_detail.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="single-post">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <div class="site-title">Suppablog</div>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Single Content -->
    <div id="content" class="site-content center-relative">
        <div class="single-post-wrapper content-1070 center-relative">

            <article class="center-relative">
                <h1 class="entry-title">
                    <!-- 글제목 -->
                    {{ post.title }}
                </h1>
                <div class="post-info content-660 center-relative">
                    <div class="cat-links">
                        <ul>
                            <li><a href="#">
                                    <!-- 카테고리 -->
                                    {% for c in post.category.all %}
                                    {{ c }}
                                    <!-- 카테고리가 여러개인 경우 , 표시 -->
                                    {% if not forloop.last %}
                                    ,
                                    {% endif %}
                                    {% endfor %}
                                </a></li>
                        </ul>
                    </div>
                    <!-- 글 작성일 -->
                    <div class="entry-date published">{{ post.createDate }}</div>
                    <div class="clear"></div>
                </div>

                <!-- 사진 -->
                {% if post.title_image %}
                <div class="post-full-width">
                    <img src="{{ post.title_image.url }}" alt="">
                </div>
                {% endif %}

                <div class=" entry-content">
                    <div class="content-wrap content-660 center-relative">
                        <!-- 글 내용 -->
                        {{ post.content }}
                        <div class="clear"></div>
                    </div>
                </div>
                <div class="clear"></div>
            </article>
        </div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>
  • 글 작성 하기 생성

blog > views.py

from django.shortcuts import render
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView

from blog.models import Category, Post

# Create your views here.


def index(req):
    post_latest = Post.objects.order_by("-createDate")[:6]      # 내림차순
    context = {
        "post_latest": post_latest
    }

    return render(req, 'index.html', context=context)


class PostDetailView(generic.DetailView):
    model = Post


class PostCreate(LoginRequiredMixin, CreateView):
    model = Post
    fields = ['title', 'title_image', 'content', 'category']

post_form.html

post_form.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="single-post">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <div class="site-title">Suppablog</div>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Single Content -->
    <div id="content" class="site-content center-relative">
        <div class="single-post-wrapper content-1070 center-relative">

            <article class="center-relative">
                <h2>새 글 작성하기</h2>
                <form action="" method="POST" enctype="multipart/form-data">
                    {% csrf_token %}
                    <table>
                        {{ form.as_table }}
                    </table>
                    <input type="submit" value="작성 완료">
                </form>
                <div class="clear"></div>
            </article>
        </div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>

blog > urls.py

from django.urls import path
from blog import views

# url 처리규칙
urlpatterns = [
    path('', views.index, name='index'),
    path("post/<int:pk>", views.PostDetailView.as_view(), name="post"),
    path("post/create", views.PostCreate.as_view(), name="post_create"),
]


  • 로그인 유/무 확인 후 글 쓰기 / 로그인 페이지 유도

index.htm

index.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <!-- static 사용을 위한 명령어 -->
    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="home blog">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <h1 class="site-title">Suppablog</h1>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <!-- 로그인 한 상태에서는 글 작성하기 보이기 -->
                    {% if user.is_authenticated %}
                    <li><a href="{% url 'post_create' %}">글 작성하기</a></li>
                    <!-- 로그인 한 상태가 아니면 로그인 보이기 -->
                    {% else %}
                    <li><a href="/admin">로그인</a></li>
                    {% endif %}
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Home Content -->
    <div id="content" class="site-content">
        <div id="blog-wrapper">
            <div class="blog-holder center-relative">
                {% for post in post_latest %}
                <!-- 첫번째 글 처리 -->
                {% if forloop.first %}
                <article id="post-1" class="blog-item-holder featured-post">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <a href="#">
                                            <!-- 카테고리 -->
                                            {% for c in post.category.all %}
                                            {{ c }}
                                            <!-- 카테고리가 여러개인 경우 , 표시 -->
                                            {% if not forloop.last %}
                                            ,
                                            {% endif %}
                                            {% endfor %}
                                        </a>
                                    </li>
                                </ul>
                            </div>
                            <!-- 글 작성일 -->
                            <div class="entry-date published">{{ post.createDate }}</div>
                            <h2 class="entry-title">
                                <!-- 글 제목 -->
                                <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                            </h2>
                            <div class="excerpt">
                                <!-- 글 내용 300자 체크 -->
                                {% if post.is_content_more300 %}
                                <!-- 300자가 안넘을경우 -->
                                {{ post.get_content_under300 }}
                                {% else %}
                                {{ post.content }}
                                {% endif %}
                                <a class="read-more" href="{{ post.get_absolute_url }}"></a>
                            </div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>
                <!-- 두번째 글 부터 -->
                {% else %}
                <article id="post-{{ forloop.counter }}" class="blog-item-holder">
                    <div class="entry-content relative">
                        <div class="content-1170 center-relative">
                            <h2 class="entry-title">
                                <!-- 글 제목 -->
                                <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                            </h2>
                            <div class="cat-links">
                                <ul>
                                    <li>
                                        <!-- 카테고리 -->
                                        <a href="#">
                                            {% for c in post.category.all %}
                                            {{ c }}
                                            <!-- 카테고리가 여러개인 경우 , 표시 -->
                                            {% if not forloop.last %}
                                            ,
                                            {% endif %}
                                            {% endfor %}
                                        </a>
                                    </li>
                                </ul>
                            </div>
                            <!-- 글 작성일 -->
                            <div class="entry-date published">{{ post.createDate }}</div>
                            <div class="clear"></div>
                        </div>
                    </div>
                </article>
                {% endif %}
                {% endfor %}
            </div>
            <div class="clear"></div>
            <div class="block load-more-holder">LOAD MORE ENTRIES</div>
        </div>

        <div class="featured-image-holder">
            <div class="featured-post-image"
                style="background-image: url({% static 'demo-images/featured-image.jpg' %})"></div>

        </div>
        <div class="clear"></div>
    </div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>
  • 템플릿의 폼 필드 조절을 위해 추가 설치
pip install django-widget-tweaks
  • 폼 필드 조절

post_form.html

post_form.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    {% load static %}

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="single-post">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <div class="site-title">Suppablog</div>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <li><a href="about.html">About</a></li>
                    <li><a href="scroll.html">Scroll</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    <!-- Single Content -->
	<div id="content" class="site-content center-relative">
		<div class="single-post-wrapper content-1070 center-relative">

			<article class="center-relative">
				<h2>새 글 작성하기</h2>
				{% load widget_tweaks %}
				<form action="" method="POST" enctype="multipart/form-data">
					{% csrf_token %}
					{% for field in form.visible_fields %}
					<div class="form-group">
						<label for="{{field.id_for_label}}">{{field.label}}</label>
						{{field|add_class:'form-control'}}
						{% for error in field.errors %}
						<span class="help-block">{{error}}</span>
						{% endfor %}
					</div>
					{% endfor %}
					<input type="submit" value="작성 완료">
				</form>
				<div class="clear"></div>
			</article>
		</div>
	</div>



    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>

anjia > settings.py

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

INSTALLED_APPS += [
    'blog.apps.BlogConfig',
    'widget_tweaks',
]
  • 중복적인 내용 제거

base_generic.html

base_generic.html
<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <title>Suppablog - Minimal Blog Html Template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <!-- static 사용을 위한 명령어 -->
    {% load static %}

    <!-- 부트스트랩 사용 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="home blog">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <h1 class="site-title">Suppablog</h1>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <!-- 로그인 한 상태에서는 글 작성하기 보이기 -->
                    {% if user.is_authenticated %}
                    <li><a href="{% url 'post_create' %}">글 작성하기</a></li>
                    <!-- 로그인 한 상태가 아니면 로그인 보이기 -->
                    {% else %}
                    <li><a href="/admin">로그인</a></li>
                    {% endif %}
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    {% block content %}
    {% endblock %}

    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>

index.html

index.html
{% extends "base_generic.html" %}
{% block content %}
{% load static %}

<!-- Home Content -->
<div id="content" class="site-content">
    <div id="blog-wrapper">
        <div class="blog-holder center-relative">
            {% for post in post_latest %}
            <!-- 첫번째 글 처리 -->
            {% if forloop.first %}
            <article id="post-1" class="blog-item-holder featured-post">
                <div class="entry-content relative">
                    <div class="content-1170 center-relative">
                        <div class="cat-links">
                            <ul>
                                <li>
                                    <a href="#">
                                        <!-- 카테고리 -->
                                        {% for c in post.category.all %}
                                        {{ c }}
                                        <!-- 카테고리가 여러개인 경우 , 표시 -->
                                        {% if not forloop.last %}
                                        ,
                                        {% endif %}
                                        {% endfor %}
                                    </a>
                                </li>
                            </ul>
                        </div>
                        <!-- 글 작성일 -->
                        <div class="entry-date published">{{ post.createDate }}</div>
                        <h2 class="entry-title">
                            <!-- 글 제목 -->
                            <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                        </h2>
                        <div class="excerpt">
                            <!-- 글 내용 300자 체크 -->
                            {% if post.is_content_more300 %}
                            <!-- 300자가 안넘을경우 -->
                            {{ post.get_content_under300 }}
                            {% else %}
                            {{ post.content }}
                            {% endif %}
                            <a class="read-more" href="{{ post.get_absolute_url }}"></a>
                        </div>
                        <div class="clear"></div>
                    </div>
                </div>
            </article>
            <!-- 두번째 글 부터 -->
            {% else %}
            <article id="post-{{ forloop.counter }}" class="blog-item-holder">
                <div class="entry-content relative">
                    <div class="content-1170 center-relative">
                        <h2 class="entry-title">
                            <!-- 글 제목 -->
                            <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                        </h2>
                        <div class="cat-links">
                            <ul>
                                <li>
                                    <!-- 카테고리 -->
                                    <a href="#">
                                        {% for c in post.category.all %}
                                        {{ c }}
                                        <!-- 카테고리가 여러개인 경우 , 표시 -->
                                        {% if not forloop.last %}
                                        ,
                                        {% endif %}
                                        {% endfor %}
                                    </a>
                                </li>
                            </ul>
                        </div>
                        <!-- 글 작성일 -->
                        <div class="entry-date published">{{ post.createDate }}</div>
                        <div class="clear"></div>
                    </div>
                </div>
            </article>
            {% endif %}
            {% endfor %}
        </div>
        <div class="clear"></div>
        <div class="block load-more-holder">LOAD MORE ENTRIES</div>
    </div>

    <div class="featured-image-holder">
        <div class="featured-post-image" style="background-image: url({% static 'demo-images/featured-image.jpg' %})">
        </div>

    </div>
    <div class="clear"></div>
</div>

{% endblock %}

post_form.html

post_form.html
{% extends "base_generic.html" %}
{% block content %}
{% load static %}

<!-- Single Content -->
<div id="content" class="site-content center-relative">
    <div class="single-post-wrapper content-1070 center-relative">

        <article class="center-relative">
            <h2>새 글 작성하기</h2>
            {% load widget_tweaks %}
            <form action="" method="POST" enctype="multipart/form-data">
                {% csrf_token %}
                {% for field in form.visible_fields %}
                <div class="form-group">
                    <label for="{{field.id_for_label}}">{{field.label}}</label>
                    {{field|add_class:'form-control'}}
                    {% for error in field.errors %}
                    <span class="help-block">{{error}}</span>
                    {% endfor %}
                </div>
                {% endfor %}
                <input type="submit" value="작성 완료">
            </form>
            <div class="clear"></div>
        </article>
    </div>
</div>
{% endblock %}
  • blog > admin.py
from django.contrib import admin
from blog.models import Category, Post

class PostAdmin(admin.ModelAdmin):
    search_fields = ['title']


admin.site.register(Category)
admin.site.register(Post, PostAdmin)
  • 템플릿들을 찾는 디렉토리 경로를 지정

anjia > settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
  • 템플릿 폴더 이동

├─anjia
│ └─__pycache__
├─blog
│ ├─migrations
│ │ └─__pycache__
│ └─__pycache__
├─media
├─static
│ ├─css
│ ├─demo-images
│ ├─fonts
│ ├─images
│ └─js
├─templates
│ └─blog

  • Favicon 설정

Download : https://freefavicon.com

파일 위치 :
루트 > favicon.ico
static > images > favicon.png

  • 글 제목에 따라 Title 테그 부분 자동으로 변경

templates > base_generic.html

<title>{% block title %}{% endblock %}</title>

templates > index.html

{% block title %}
AnJiA PhotoBlog
{% endblock %}

templates > blog > post_detail.html

{% block title %}
{{ post.title }}
{% endblock %}
  • 개발자 모드에서 간섭으로 인한 정렬 문제 현상 확인으로 style 적용 정렬(추후 확인예정)

templates > blog > post_detail.html

<h1 style="text-align:center" class="entry-title">

<div style="text-align:right" class="post-info content-660 center-relative">
  • detail 페이지 사진 정렬 / 사이즈 조절

static > css > style.css

.content-660 img,
.content-1070 img,
.content-900 img {
  max-width: 50%;
  max-height: 50%;
  width: auto;
  height: auto;
  display: block;
  margin: 0px auto;
}
  • Login 페이지 수정 작업(로그인 후 메인화면 이동)

anjia > settings.py

LOGIN_REDIRECT_URL = '/'

anjia > urls.py

from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from django.views.generic import RedirectView
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth import views as auth_views


# http://localhost:8000/ => http://localhost:8000/blog
urlpatterns = [
    path('admin/', admin.site.urls),
    path("blog/", include("blog.urls")),
    path("", RedirectView.as_view(url="/blog/", permanent=True)),
    path('accounts/login/', auth_views.LoginView.as_view(), name='login'),
]

urlpatterns += static(settings.STATIC_URL,
                      document_root=settings.STATIC_ROOT)     # staic 정적 파일 처리
urlpatterns += static(settings.MEDIA_URL,
                      document_root=settings.MEDIA_ROOT)     # media 정적 파일 처리

templates > base_generic.html

base_generic.html
<!DOCTYPE HTML>
<html lang="ko">

<head>
    <title>{% block title %}{% endblock %}</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <!-- static 사용을 위한 명령어 -->
    {% load static %}

    <!-- 부트스트랩 사용 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="home blog">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <h1 class="site-title">Suppablog</h1>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <!-- 로그인 한 상태에서는 글 작성하기 보이기 -->
                    {% if user.is_authenticated %}
                    <li><a href="{% url 'post_create' %}">글 작성하기</a></li>
                    <!-- 로그인 한 상태가 아니면 로그인 보이기 -->
                    {% else %}
                    <li><a href="/accounts/login">로그인</a></li>
                    {% endif %}
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    {% block content %}
    {% endblock %}

    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>

templates > registration > login.html

login.html
{% extends "base_generic.html" %}

{% block content %}

<div class="container">
    <h1>Login</h1>

    {% if form.errors %}
    <p>이름과 비밀번호가 일치하지 않습니다. 다시 시도해주세요.</p>
    {% endif %}

    <form method="post" action="{% url 'login' %}">
        {% csrf_token %}
        <table>
            <th>{{ form.username.label_tag }}</th>
            <th></th>
            <tr></tr>
            <tr>
                <td>{{ form.username }}</td>
            </tr>
            <th>{{ form.password.label_tag }}</th>
            <th></th>
            <tr></tr>
            <tr>
                <td>{{ form.password }}</td>
            </tr>
        </table>
        <br>
        <input type="submit" value="login" />
        <input type="hidden" name="next" value="{{ next }}" />
    </form>
</div>
</div>

{% endblock %}
  • Logout 페이지 수정 작업(로그아웃 후 메인화면 이동)

anjia > settings.py

LOGOUT_REDIRECT_URL = '/'

anjia > urls.py

from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from django.views.generic import RedirectView
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth import views as auth_views


# http://localhost:8000/ => http://localhost:8000/blog
urlpatterns = [
    path('admin/', admin.site.urls),
    path("blog/", include("blog.urls")),
    path("", RedirectView.as_view(url="/blog/", permanent=True)),
    path('accounts/login/', auth_views.LoginView.as_view(), name='login'),
    path('accounts/logout/', auth_views.LogoutView.as_view(),
         name='logout', kwargs={'next_page': '/'}),
]

urlpatterns += static(settings.STATIC_URL,
                      document_root=settings.STATIC_ROOT)     # staic 정적 파일 처리
urlpatterns += static(settings.MEDIA_URL,
                      document_root=settings.MEDIA_ROOT)     # media 정적 파일 처리

templates > base_generic.html

base_generic.html
<!DOCTYPE HTML>
<html lang="ko">

<head>
    <title>{% block title %}{% endblock %}</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <!-- static 사용을 위한 명령어 -->
    {% load static %}

    <!-- 부트스트랩 사용 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href='http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700'
        rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />

    <!--[if lt IE 9]>
                <script src="{% static 'js/html5.js' %}"></script>
        <![endif]-->

</head>


<body class="home blog">

    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading...">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:">
                </label>
            </div>
            <div class="site-info-holder">
                <h1 class="site-title">Suppablog</h1>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <!-- 로그인 한 상태에서는 글 작성하기 보이기 -->
                    {% if user.is_authenticated %}
                    <li><a href="{% url 'post_create' %}">글 작성하기</a></li>
                    <li><a href="/accounts/logout">로그아웃</a></li>
                    <!-- 로그인 한 상태가 아니면 로그인 보이기 -->
                    {% else %}
                    <li><a href="/accounts/login">로그인</a></li>
                    {% endif %}
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br> CRAFTED WITH <i class="fa fa-heart"></i> BY <a
                        href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP">
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top"><i class="fa fa-caret-square-o-up" aria-hidden="true"></i></div>
        </div>
        <div class="clear"></div>
    </div>

    {% block content %}
    {% endblock %}

    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type='text/javascript' src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type='text/javascript' src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type='text/javascript' src='{% static "js/main.js" %}'></script>
</body>

</html>
  • 로그인 페이지 가운데 정렬

static > css > login_form.css

.container {
  text-align: center;
}

.co {
  display: inline-block;
}

h1 {
  text-align: center;
}

table {
  text-align: center;
}

templates > base_generic.html

base_generic.html
<link rel="stylesheet" type="text/css" href='{% static "css/login_form.css" %}' />

templates > registration > login.html

{% extends "base_generic.html" %}

{% block content %}

<div class="container">
    <h1>Admin Login Page</h1>

    {% if form.errors %}
    <p>이름과 비밀번호가 일치하지 않습니다. 다시 시도해주세요.</p>
    {% endif %}
    <div class="co">
    <form class="login_form" method="post" action="{% url 'login' %}">
        {% csrf_token %}
        <table>
            <th>관리자 아이디</th>
            <tr></tr>
            <tr>
                <td>{{ form.username }}</td>
            </tr>
            <th>관리자 패스워드</th>
            <tr></tr>
            <tr>
                <td>{{ form.password }}</td>
            </tr>
        </table>
        <br>
        <div class="form-row text-center">
            <div class="col-12">
            <input class="btn btn-primary btn-lg btn-block" type="submit" value="login" />
            <input type="hidden" name="next" value="{{ next }}" />
            </div>
        </div>
    </form>
</div>
</div>
</div>

{% endblock %}
  • 전체 보기 페이지 작성

templates > blog > post_list.html

post_list.html
{% extends "base_generic.html" %}
{% block content %}
{% load static %}

<div class="container my-0">
    <table class="table">
        <thead>
            <tr class="thead-dark">
                <th>번호</th>
                <th>제목</th>
                <th>작성일시</th>
            </tr>
        </thead>
        <tbody>
            {% if posts %}
            {% for post in posts %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></td>
                <td>{{ post.createDate }}</td>
            </tr>
            {% endfor %}
            {% else %}
            <tr>
                <td colspan="3">글이 없습니다.</td>
            </tr>
            {% endif %}
        </tbody>
    </table>
    <ul class="pagination justify-content-center">
        {% if posts.has_previous %}
        <li class="page-item">
            <a class="page-link" href="?page={{ posts.previous_page_number }}">이전</a>
        </li>
        {% else %}
        <li class="page-item disabled">
            <a class="page-link" tabindex="-1" aria-disabled="true" href="#">이전</a>
        </li>
        {% endif %}

        {% for page_number in posts.paginator.page_range %}
        {% if posts.number|add:-5 <= page_number <= posts.number|add:5 %}
        {% if page_number == posts.number %}
        <li class="page-item active" aria-current="page">
            <a class="page-link" href="?page={{ page_number }}">{{ page_number }}</a>
        </li>
        {% else %}
        <li class="page-item">
            <a class="page-link" href="?page={{ page_number }}">{{ page_number }}</a>
        </li>
        {% endif %}
        {% endif %}
        {% endfor %}

        {% if posts.has_next %}
        <li class="page-item">
            <a class="page-link" href="?page={{ posts.next_page_number }}">다음</a>
        </li>
        {% else %}
        <li class="page-item disabled">
            <a class="page-link" tabindex="-1" aria-disabled="true" href="#">다음</a>
        </li>
        {% endif %}
    </ul>
</div>


{% endblock %}

templates > base_generic.html

base_generic.html
<!DOCTYPE html>
<html lang="ko">

<head>
    <title>{% block title %}{% endblock %}</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="description" content="Template by Colorlib" />
    <meta name="keywords" content="HTML, CSS, JavaScript, PHP" />
    <meta name="author" content="Colorlib" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />

    <!-- static 사용을 위한 명령어 -->
    {% load static %}

    <!-- 부트스트랩 사용 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" />

    <link rel="shortcut icon" href="{% static 'images/favicon.png' %}" />
    <link href="http://fonts.googleapis.com/css?family=Montserrat:400,700%7CLibre+Baskerville:400,400italic,700"
        rel="stylesheet" type="text/css" />
    <link rel="stylesheet" type="text/css" href='{% static "css/clear.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/common.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/font-awesome.min.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/carouFredSel.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/sm-clean.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/style.css" %}' />
    <link rel="stylesheet" type="text/css" href='{% static "css/login_form.css" %}' />

    <!--[if lt IE 9]>
      <script src="{% static 'js/html5.js' %}"></script>
    <![endif]-->
</head>

<body class="home blog">
    <!-- Preloader Gif -->
    <table class="doc-loader">
        <tbody>
            <tr>
                <td>
                    <img src="{% static 'images/ajax-document-loader.gif' %}" alt="Loading..." />
                </td>
            </tr>
        </tbody>
    </table>

    <!-- Left Sidebar -->
    <div id="sidebar" class="sidebar">
        <div class="menu-left-part">
            <div class="search-holder">
                <label>
                    <input type="search" class="search-field" placeholder="Type here to search..." value="" name="s"
                        title="Search for:" />
                </label>
            </div>
            <div class="site-info-holder">
                <h1 class="site-title">Suppablog</h1>
                <p class="site-description">
                    Suppablog is simple and yet cool wordpress theme to lorem ipsum
                    dolor sit.
                </p>
            </div>
            <nav id="header-main-menu">
                <ul class="main-menu sm sm-clean">
                    <li><a href="{% url 'index' %}" class="current">Home</a></li>
                    <!-- 로그인 한 상태에서는 글 작성하기 보이기 -->
                    {% if user.is_authenticated %}
                    <li><a href="{% url 'post_create' %}">글 작성하기</a></li>
                    <li><a href="{% url 'post_list' %}">전체보기</a></li>
                    <li><a href="/accounts/logout">로그아웃</a></li>
                    <!-- 로그인 한 상태가 아니면 로그인 보이기 -->
                    {% else %}
                    <li><a href="/accounts/login">로그인</a></li>
                    {% endif %}
                </ul>
            </nav>
            <footer>
                <div class="footer-info">
                    ⓒ 2018 SUPPABLOG HTML TEMPLATE. <br />
                    CRAFTED WITH <i class="fa fa-heart"></i> BY
                    <a href="https://colorlib.com">COLORLIB</a>.
                </div>
            </footer>
        </div>
        <div class="menu-right-part">
            <div class="logo-holder">
                <a href="{% url 'index' %}">
                    <img src="{% static 'images/logo.png' %}" alt="Suppablog WP" />
                </a>
            </div>
            <div class="toggle-holder">
                <div id="toggle">
                    <div class="menu-line"></div>
                </div>
            </div>
            <div class="social-holder">
                <div class="social-list">
                    <a href="#"><i class="fa fa-twitter"></i></a>
                    <a href="#"><i class="fa fa-youtube-play"></i></a>
                    <a href="#"><i class="fa fa-facebook"></i></a>
                    <a href="#"><i class="fa fa-vimeo"></i></a>
                    <a href="#"><i class="fa fa-behance"></i></a>
                    <a href="#"><i class="fa fa-rss"></i></a>
                </div>
            </div>
            <div class="fixed scroll-top">
                <i class="fa fa-caret-square-o-up" aria-hidden="true"></i>
            </div>
        </div>
        <div class="clear"></div>
    </div>

    {% block content %} {% endblock %}

    <!--Load JavaScript-->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type="text/javascript" src='{% static "js/imagesloaded.pkgd.js" %}'></script>
    <script type="text/javascript" src='{% static "js/jquery.nicescroll.min.js" %}'></script>
    <script type="text/javascript" src='{% static "js/jquery.smartmenus.min.js" %}'></script>
    <script type="text/javascript" src='{% static "js/jquery.carouFredSel-6.0.0-packed.js" %}'></script>
    <script type="text/javascript" src='{% static "js/jquery.mousewheel.min.js" %}'></script>
    <script type="text/javascript" src='{% static "js/jquery.touchSwipe.min.js" %}'></script>
    <script type="text/javascript" src='{% static "js/jquery.easing.1.3.js" %}'></script>
    <script type="text/javascript" src='{% static "js/main.js" %}'></script>
</body>

</html>

blog > views.py

from django.shortcuts import render
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from django.core.paginator import Paginator

from blog.models import Category, Post

# Create your views here.


def index(req):
    post_latest = Post.objects.order_by("-createDate")[:]      # 내림차순
    context = {
        "post_latest": post_latest
    }

    return render(req, 'index.html', context=context)


class PostDetailView(generic.DetailView):
    model = Post


class PostCreate(LoginRequiredMixin, CreateView):
    model = Post
    fields = ['title', 'title_image', 'content', 'category']


def post_list(req):
    page = int(req.GET.get('page', '1'))
    posts = Post.objects.order_by("-createDate")

    paginator = Paginator(posts, 10)
    page_obj = paginator.get_page(page)

    context = {
        'posts': page_obj
    }

    return render(req, 'blog/post_list.html', context=context)
  • 메인 페이지 300자 이상 넘을시 ... 으로 표현

templates > index.html

index.html
{% extends "base_generic.html" %}

{% block title %}
AnJiA PhotoBlog
{% endblock %}

{% block content %}
{% load static %}

<!-- Home Content -->
<div id="content" class="site-content">
    <div id="blog-wrapper">
        <div class="blog-holder center-relative">
            {% for post in post_latest %}
            <!-- 첫번째 글 처리 -->
            {% if forloop.first %}
            <article id="post-1" class="blog-item-holder featured-post">
                <div class="entry-content relative">
                    <div class="content-1170 center-relative">
                        <div class="cat-links">
                            <ul>
                                <li>
                                    <a href="#">
                                        <!-- 카테고리 -->
                                        {% for c in post.category.all %}
                                        {{ c }}
                                        <!-- 카테고리가 여러개인 경우 , 표시 -->
                                        {% if not forloop.last %}
                                        ,
                                        {% endif %}
                                        {% endfor %}
                                    </a>
                                </li>
                            </ul>
                        </div>
                        <!-- 글 작성일 -->
                        <div class="entry-date published">{{ post.createDate }}</div>
                        <h2 class="entry-title">
                            <!-- 글 제목 -->
                            <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                        </h2>
                        <div class="excerpt">
                            <!-- 글 내용은 300자를 초과하면 ...으로 표시 -->
                            {{ post.content|truncatechars:300 }}
                            <a class="read-more" href="{{ post.get_absolute_url }}"></a>
                        </div>
                        <div class="clear"></div>
                    </div>
                </div>
            </article>
            <!-- 두번째 글 부터 -->
            {% else %}
            <article id="post-{{ forloop.counter }}" class="blog-item-holder">
                <div class="entry-content relative">
                    <div class="content-1170 center-relative">
                        <h2 class="entry-title">
                            <!-- 글 제목 -->
                            <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
                        </h2>
                        <div class="cat-links">
                            <ul>
                                <li>
                                    <!-- 카테고리 -->
                                    <a href="#">
                                        {% for c in post.category.all %}
                                        {{ c }}
                                        <!-- 카테고리가 여러개인 경우 , 표시 -->
                                        {% if not forloop.last %}
                                        ,
                                        {% endif %}
                                        {% endfor %}
                                    </a>
                                </li>
                            </ul>
                        </div>
                        <!-- 글 작성일 -->
                        <div class="entry-date published">{{ post.createDate }}</div>
                        <div class="clear"></div>
                    </div>
                </div>
            </article>
            {% endif %}
            {% endfor %}
        </div>
        <div class="clear"></div>
        <div class="block load-more-holder">LOAD MORE ENTRIES</div>
    </div>

    <div class="featured-image-holder">
        <div class="featured-post-image" style="background-image: url({% static 'demo-images/featured-image.jpg' %})">
        </div>

    </div>
    <div class="clear"></div>
</div>

{% endblock %}
  • 돌잔치 전용 페이지 생성

blog/urls.py

path('post/video/', views.post_video, name='post_video'),

blog/views.py

def post_video(req):
    return render(req, 'blog/post_video.html', context=context)

templates/base_generic.html

<li><a href="{% url 'post_video' %}">성장영상</a></li>

templates/blog/post_video.html

{% extends "base_generic.html" %}
{% block content %}

{% load static %}

<div class="content container">
    <header class="page-header">
        <h3></h3>
    </header>
    <div class="row">
        <div class="col-md-16" style="float: none; margin: 0 auto;">
            <div id="player">
                <video width=800px height=auto controls autoplay>
                    <source src="{% static 'media/video.mp4' %}" type="video/mp4">
               </video>
   <a href="https://map.naver.com/v5/?c=14124581.9639330,4500587.2340440,15,0,0,0,dh&lng=126.8832786&lat=37.4397958&type=0&title=%EA%B2%BD%EA%B8%B0%EB%8F%84%20%EA%B4%91%EB%AA%85%EC%8B%9C%20%EC%86%8C%ED%95%98%EB%8F%99%201365%20%EB%A7%88%EB%B2%A0%EB%B9%8C%EB%A0%88%20(%EA%B5%AC)%EB%B2%A8%EB%9D%BC%EC%98%A4%EC%8A%A4%ED%8B%B4"
       target="_blank"><img src="{% static 'etc/jido.jpg' %}" style="width: 55%; height: auto;" /></a>

{% endblock %} </source>

  • social-holder를 위한 font-awesome 추가 설정

templates/base_generic.html

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"
        integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
  • social-holder 조절

templates/base_generic.html

<div class="social-holder">
                <div class="social-list">
                    <a href="https://developer-ankiwoong.tistory.com/" target="_blank"><i class="fas fa-blog"></i></a>
                    <a href="https://github.com/ankiwoong/" target="_blank"><i class="fab fa-github"></i></a>
                </div>
            </div>
  • SECRET_KEY 보안 작업

※ 추후 작업 배포시 secrets.json 제외 하고 올려야됨 anjia/settings.py

from django.core.exceptions import ImproperlyConfigured

import os
import json

secret_file = os.path.join(BASE_DIR, 'secrets.json')

with open(secret_file) as f:
    secrets = json.loads(f.read())


def get_secret(setting, secrets=secrets):
    try:
        # print(secrets[setting])
        return secrets[setting]
    except KeyError:
        error_msg = "Set the {0} environment variable".format(setting)
        raise ImproperlyConfigured(error_msg)


SECRET_KEY = get_secret("SECRET_KEY")

/secrets.json

{
  "SECRET_KEY": ""
}
  • 관리자 페이지 레이아웃 구성 변경

anjia > admin.py

from django.contrib import admin
from blog.models import Category, Post


class PostAdmin(admin.ModelAdmin):
    search_fields = ['title']           # 제목으로 검색
    list_per_page = 5                   # 한 페이지에 보이는 갯수
    list_display = ('id', 'title', 'content', 'createDate',
                    'updateDate')       # 페이지에 보이는 내용
    list_filter = ('category', )        # 필터링 작업

    # 레이아웃
    fieldsets = [
        ('제목', {'fields': ['title']}),
        ('내용', {'fields': ['content']}),
        ('카테고리', {'fields': ['category']}),
        # ('날짜', {'fields': ['createDate']}),
    ]


admin.site.register(Category)
admin.site.register(Post, PostAdmin)
  • 세션 적용

anjia > admin.py

# Close the session when user closes the browser
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
  • BSD 2-Clause "Simplified" License

https://ko.wikipedia.org/wiki/BSD_%ED%97%88%EA%B0%80%EC%84%9C

Permissions Limitations Conditions
O Commercial use X Liability License and copyright notice
O Modification X Warranty
O Distribution
O Private use

\licence

Copyright (c) 2020, Ankiwoong

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  • robots.txt

모든 크롤링 금지 \robots.txt

User-agent: *
Disallow: /
  • SEO 설정

templates > base_generic.html

<!-- SEO -->
<meta name="description" content="The growth blog of my beloved daughter" />
<meta name="keywords" content="HTML, CSS, JavaScript, Python, Djaong" />
<meta name="author" content="AnKiWoong" />
  • log 수정 작업

anjia/settings.py

# Loging
# Loging Level : DEBUG < INFO < WARNING < ERROR < CRITICAL
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            # asctime - 현재시간
            # levelname - 로그의 레벨 (debug, info, warning, error, critical)
            # name - 로거이름
            # lineno - 라인 번호
            # message - 출력내용
            'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
            'datefmt': "%d/%b/%Y %H:%M:%S"
        },
    },
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(BASE_DIR, 'logs', 'logs.log'),
            'formatter': 'verbose',
            'encoding': 'utf-8',
        },
    },
    'loggers': {
        'blog': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'backupCount': 5,
            'maxBytes': 1024*1024*5,
        },
    }
}

blog/views.py

from django.shortcuts import render
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from django.core.paginator import Paginator

from blog.models import Category, Post

import logging

logger = logging.getLogger('blog')


def index(req):
    logger.info("log level : info / view > index")
    post_latest = Post.objects.order_by("-createDate")[:5]      # 내림차순
    context = {
        "post_latest": post_latest
    }

    return render(req, 'index.html', context=context)


class PostDetailView(generic.DetailView):
    logger.error("log level : ERROR / view > DetailView")
    model = Post


class PostCreate(LoginRequiredMixin, CreateView):
    logger.error("log level : ERROR / view > CreateView")
    model = Post
    fields = ['title', 'title_image', 'content', 'category']


def post_list(req):
    logger.info("log level : info / view > post_list")
    page = int(req.GET.get('page', '1'))
    posts = Post.objects.order_by("-createDate")

    paginator = Paginator(posts, 10)
    page_obj = paginator.get_page(page)

    context = {
        'posts': page_obj
    }

    return render(req, 'blog/post_list.html', context=context)


def post_video(req):
    return render(req, 'blog/post_video.html')

[21/May/2020 20:05:50] ERROR [blog:25] log level : ERROR / view > DetailView [21/May/2020 20:05:50] ERROR [blog:30] log level : ERROR / view > CreateView [21/May/2020 20:05:56] ERROR [blog:25] log level : ERROR / view > DetailView [21/May/2020 20:05:56] ERROR [blog:30] log level : ERROR / view > CreateView [21/May/2020 20:06:05] ERROR [blog:25] log level : ERROR / view > DetailView [21/May/2020 20:06:05] ERROR [blog:30] log level : ERROR / view > CreateView [21/May/2020 20:06:14] INFO [blog:15] log level : info / view > index [21/May/2020 20:06:22] INFO [blog:36] log level : info / view > post_list [21/May/2020 20:06:25] INFO [blog:15] log level : info / view > index

  • 보안 작업 - 로그인 IP 로깅에 기록

blog > apps.py

from django.apps import AppConfig


class BlogConfig(AppConfig):
    name = 'blog'

    verbose_name = 'blog'

    def ready(self):
        import blog.signals

blog > signals.py

import logging
from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from django.dispatch import receiver

log = logging.getLogger(__name__)


@receiver(user_logged_in)
def user_logged_in_callback(sender, request, user, **kwargs):
    ip = request.META.get('REMOTE_ADDR')

    log.debug('login user: {user} ip: {ip}'.format(
        user=user,
        ip=ip
    ))


@receiver(user_logged_out)
def user_logged_out_callback(sender, request, user, **kwargs):
    ip = request.META.get('REMOTE_ADDR')

    log.debug('logout user: {user} ip: {ip}'.format(
        user=user,
        ip=ip
    ))


@receiver(user_login_failed)
def user_login_failed_callback(sender, credentials, **kwargs):
    log.warning('logout failed for: {credentials}'.format(
        credentials=credentials,
    ))
  • 로그인 / 로그아웃 정보 로깅 기록 작업

blog > views.py

from django.shortcuts import render
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from django.core.paginator import Paginator

from blog.models import Category, Post

import logging

logger = logging.getLogger('blog')


def index(req):
    logger.info("log level : info / view > index")
    post_latest = Post.objects.order_by("-createDate")[:5]      # 내림차순
    context = {
        "post_latest": post_latest
    }

    return render(req, 'index.html', context=context)


class PostDetailView(generic.DetailView):
    logger.error("log level : ERROR / view > DetailView")
    model = Post


class PostCreate(LoginRequiredMixin, CreateView):
    logger.error("log level : ERROR / view > CreateView")
    model = Post
    fields = ['title', 'title_image', 'content', 'category']


def post_list(req):
    logger.info("log level : info / view > post_list")
    page = int(req.GET.get('page', '1'))
    posts = Post.objects.order_by("-createDate")

    paginator = Paginator(posts, 10)
    page_obj = paginator.get_page(page)

    context = {
        'posts': page_obj
    }

    return render(req, 'blog/post_list.html', context=context)


def post_video(req):
    return render(req, 'blog/post_video.html')
  • Login page 수정 작업

templates > registration > login.html

{% extends "base_generic.html" %}

{% block content %}

<div class="container">
    <h1>Admin Login Page</h1>

    {% if form.errors %}
    <p>관리자 계정을 정확하게 입력 하세요.</p>
    {% endif %}

    <div class="container my-3">
        <div class="row justify-content-center align-self-center">
            <form class="login_form" method="post" action="{% url 'login' %}">
                {% csrf_token %}
                <div class="form-group">
                    <label for="username">관리자 ID</label>
                    <input type="text" class="form-control" name="username" id="username"
                        value="{{ form.username.value|default_if_none:'' }}">
                </div>
                <div class="form-group">
                    <label for="password">관리자 PW</label>
                    <input type="password" class="form-control" name="password" id="password"
                        value="{{ form.password.value|default_if_none:'' }}">
                </div>
                <div class="form-row text-center">
                    <div class="col-12">
                        <input class="btn btn-primary btn-lg btn-block" type="submit" value="로그인" />
                        <input type="hidden" name="next" value="{{ next }}" />
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

{% endblock %}
  • 400 Bad Request 페이징 처리

anjia > urls.py

from django.conf.urls import handler400

handler400 = 'blog.views.error400'

blog > views.py

def error400(req, exception):
    return render(req, "errors/400.html", status=400)

templates > errors > 400.html

{% extends 'base_generic.html' %}
{% block content %}
{% block title %} Bad Request 400 {% endblock %}
<div class="container" style="margin-top:20px;">
    <div class="row">
        <div class="col-sm-12 col-md-6 offset-md-3">
            <div class="card">
                <div class="card-header">
                    Bad Request - Error 400
                </div>
                <div class="card-block">
                    <p class="lead">
                        The server could not understand the request due to invalid syntax.
                    </p>
                    <a href="/" class="btn btn-link">Return HOME</a>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}
  • 403 Forbidden 페이징 처리

anjia > urls.py

from django.conf.urls import handler403

handler403 = 'blog.views.error403'

blog > views.py

def error403(req, exception):
    return render(req, "errors/403.html", status=403)

templates > errors > 403.html

{% extends 'base_generic.html' %}
{% block content %}
{% block title %} Forbidden 403 {% endblock %}
<div class="container" style="margin-top:20px;">
    <div class="row">
        <div class="col-sm-12 col-md-6 offset-md-3">
            <div class="card">
                <div class="card-header">
                    Forbidden - Error 403
                </div>
                <div class="card-block">
                    <p class="lead">
                        The client does not have access rights to the content.
                    </p>
                    <a href="/" class="btn btn-link">Return HOME</a>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}
  • 404 Not Found 페이징 처리

anjia > urls.py

from django.conf.urls import handler404

handler404 = 'blog.views.error404'

blog > views.py

def error404(req, exception):
    return render(req, "errors/404.html", status=404)

templates > errors > 404.html

{% extends 'base_generic.html' %}
{% block content %}
{% block title %} Not Found 404 {% endblock %}
<div class="container" style="margin-top:20px;">
    <div class="row">
        <div class="col-sm-12 col-md-6 offset-md-3">
            <div class="card">
                <div class="card-header">
                    Not Found - Error 404
                </div>
                <div class="card-block">
                    <p class="lead">
                        The server can not find the requested resource.
                    </p>
                    <a href="/" class="btn btn-link">Return HOME</a>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}
  • 500 Internal Server Error 페이징 처리

anjia > urls.py

from django.conf.urls import handler500

handler500 = 'blog.views.error500'

blog > views.py

def error500(req):
    return render(req, "errors/500.html", status=500)

templates > errors > 500.html

{% extends 'base_generic.html' %}
{% block content %}
{% block title %} Internal Server Error 500 {% endblock %}
<div class="container" style="margin-top:20px;">
    <div class="row">
        <div class="col-sm-12 col-md-6 offset-md-3">
            <div class="card">
                <div class="card-header">
                    Forbidden - Error 500
                </div>
                <div class="card-block">
                    <p class="lead">
                        The server has encountered a situation it doesn't know how to handle.
                    </p>
                    <a href="/" class="btn btn-link">Return HOME</a>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}
  • 댓글 기능 활성화(disqus)

disqus 설치

pip install django-disqus

six 설치

pip install six

anjia > settings.py

INSTALLED_APPS += [
    'disqus',
    'django.contrib.sites',
]

DISQUS_WEBSITE_SHORTNAME = 'disqus 가입 아이디'
SITE_ID = 1

templates > post_detail.html

    <div class="row">
         <div class="col-md-2"></div>
             <div class="col-md-8 panel panel-default">
                {% load disqus_tags %}
                {% disqus_show_comments %}
            </div>
        <div class="col-md-2"></div>
     </div>
  • 글 내용에서 행이 바뀌면 문단으로 변환

templates > blog > post_detail.html

<div class="content-wrap content-660 center-relative">
                <div class="wrap-blockquot">
                    {{ post.content|linebreaksbr }}
                </div>
            </div>
  • 로그인 후 index 페이지 수정
{% if user.is_authenticated %}
            <div style="text-align: center; color: wheat; font-size: 40px; margin-top: 20px;">
                <i class="far fa-id-badge"> {{user.get_username}} </i>
            </div>
            {% else %}
            <div style="text-align: center; color: white; font-size: 40px; margin-top: 20px;">
                <i class="far fa-id-badge"></i>
            </div>
            {% endif %}
            <div class="site-info-holder">
                <p class="site-description">
                    Language : Python - Django<br>
                    Coder : AnKiWoong<br>
                </p>
            </div>

3.3.8 Error Log

  • 2020.05.18 / 로깅을 찍어봐도 에러 원인 알 수 없음 / 가끔 나오는 오류 / 모든 페이지 기능 정상 작동
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\ankiwoong\AppData\Local\Programs\Python\Python37\lib\socketserver.py", line 650, in process_request_thread
    self.finish_request(request, client_address)
  File "C:\Users\ankiwoong\AppData\Local\Programs\Python\Python37\lib\socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:\Users\ankiwoong\AppData\Local\Programs\Python\Python37\lib\socketserver.py", line 720, in __init__
    self.handle()
  File "C:\Python_kindergarten\venv\lib\site-packages\django\core\servers\basehttp.py", line 174, in handle       
    self.handle_one_request()
  File "C:\Python_kindergarten\venv\lib\site-packages\django\core\servers\basehttp.py", line 197, in handle_one_request
    handler.run(self.server.get_app())
  File "C:\Users\ankiwoong\AppData\Local\Programs\Python\Python37\lib\wsgiref\handlers.py", line 144, in run      
    self.close()
  File "C:\Python_kindergarten\venv\lib\site-packages\django\core\servers\basehttp.py", line 114, in close        
    super().close()
  File "C:\Users\ankiwoong\AppData\Local\Programs\Python\Python37\lib\wsgiref\simple_server.py", line 35, in close
    self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
  • 2020.05.19 / 배포 테스트 작업 진행 중 media 설정 값을 인식 못하는 현상 발생

└ <해결 완료> 서빙 경로 지정 중 오타로 인한 media 폴더 인식 불가능 (/media/\ -> /media/)

Failed to load resource: the server responded with a status of 404 (Not Found)

python bash tree 구조 상 media 폴더는 존재 및 파일은 정상적으로 업로드 됨 / 해당 문제 파악 최우선

├── README.md                                                                                                                                         
├── anjia                                                                                                                                             
│   ├── __init__.py                                                                                                                                   
│   ├── __pycache__                                                                                                                                   
│   │   ├── __init__.cpython-37.pyc                                                                                                                   
│   │   ├── settings.cpython-37.pyc                                                                                                                   
│   │   └── urls.cpython-37.pyc                                                                                                                       
│   ├── asgi.py                                                                                                                                       
│   ├── settings.py                                                                                                                                   
│   ├── urls.py                                                                                                                                       
│   └── wsgi.py                                                                                                                                       
├── blog                                                                                                                                              
│   ├── __init__.py                                                                                                                                   
│   ├── __pycache__                                                                                                                                   
│   │   ├── __init__.cpython-37.pyc                                                                                                                   
│   │   ├── admin.cpython-37.pyc                                                                                                                      
│   │   ├── apps.cpython-37.pyc                                                                                                                       
│   │   ├── models.cpython-37.pyc                                                                                                                     
│   │   ├── urls.cpython-37.pyc                                                                                                                       
│   │   └── views.cpython-37.pyc                                                                                                                      
│   ├── admin.py                                                                                                                                      
│   ├── apps.py                                                                                                                                       
│   ├── migrations                                                                                                                                    
│   │   ├── 0001_initial.py                                                                                                                           
│   │   ├── __init__.py                                                                                                                               
│   │   └── __pycache__                                                                                                                               
│   │   ├── fontawesome-webfont.ttf
│   │       ├── 0001_initial.cpython-37.pyc                                                                                                           
│   │       └── __init__.cpython-37.pyc                                                                                                               
│   ├── models.py                                                                                                                                     
│   ├── tests.py                                                                                                                                      
│   ├── urls.py                                                                                                                                       
│   └── views.py                                                                                                                                      
├── db.sqlite3                                                                                                                                        
├── favicon.ico                                                                                                                                       
├── logs                                                                                                                                              
├── manage.py                                                                                                                                         
├── media                                                                                                                                             
│   ├── 1.jpg                                                                                                                                         
│   └── 54277386_2032634540377169_2842198792864861504_n.jpg                                                                                           
├── secrets.json                                                                                                                                      
├── static
│   ├── admin
│   │   ├── css
│   │   │   ├── autocomplete.css
│   │   │   ├── base.css
│   │   │   ├── changelists.css
│   │   │   ├── dashboard.css
│   │   │   ├── fonts.css
│   │   │   ├── forms.css
│   │   │   ├── login.css
│   │   │   ├── responsive.css
│   │   │   ├── responsive_rtl.css
│   │   │   ├── rtl.css
│   │   │   ├── vendor
│   │   │   │   └── select2
│   │   │   │       ├── LICENSE-SELECT2.md
│   │   │   │       ├── select2.css
│   │   │   │       └── select2.min.css
│   │   │   └── widgets.css
│   │   ├── fonts
│   │   │   ├── LICENSE.txt
│   │   │   ├── README.txt
│   │   │   ├── Roboto-Bold-webfont.woff
│   │   │   ├── Roboto-Light-webfont.woff
│   │   │   └── Roboto-Regular-webfont.woff
│   │   ├── img
│   │   │   ├── LICENSE
│   │   │   ├── README.txt
│   │   │   ├── calendar-icons.svg
│   │   │   ├── gis
│   │   │   │   ├── move_vertex_off.svg
│   │   │   │   └── move_vertex_on.svg
│   │   │   ├── icon-addlink.svg
│   │   │   ├── icon-alert.svg
│   │   │   ├── icon-calendar.svg
│   │   │   ├── icon-changelink.svg
│   │   │   ├── icon-clock.svg
│   │   │   ├── icon-deletelink.svg
│   │   │   ├── icon-no.svg
│   │   │   ├── icon-unknown-alt.svg
│   │   │   ├── icon-unknown.svg
│   │   │   ├── icon-viewlink.svg
│   │   │   ├── icon-yes.svg
│   │   │   ├── inline-delete.svg
│   │   │   ├── search.svg
│   │   │   ├── selector-icons.svg
│   │   │   ├── sorting-icons.svg
│   │   │   ├── tooltag-add.svg
│   │   │   └── tooltag-arrowright.svg
│   │   └── js
│   │       ├── SelectBox.js
│   │       ├── SelectFilter2.js
│   │       ├── actions.js
│   │       ├── actions.min.js
│   │       ├── admin
│   │       │   ├── DateTimeShortcuts.js
│   │       │   └── RelatedObjectLookups.js
│   │       ├── autocomplete.js
│   │       ├── calendar.js
│   │       ├── cancel.js
│   │       ├── change_form.js
│   │       ├── collapse.js
│   │       ├── collapse.min.js
│   │       ├── core.js
│   │       ├── inlines.js
│   │       ├── inlines.min.js
│   │       ├── jquery.init.js
│   │       ├── popup_response.js
│   │       ├── prepopulate.js
│   │       ├── prepopulate.min.js
│   │       ├── prepopulate_init.js
│   │       ├── urlify.js
│   │       └── vendor
│   │           ├── jquery
│   │           │   ├── LICENSE.txt
│   │           │   ├── jquery.js
│   │           │   └── jquery.min.js
│   │           ├── select2
│   │           │   ├── LICENSE.md
│   │           │   ├── i18n
│   │           │   │   ├── af.js
│   │           │   │   ├── ar.js
│   │           │   │   ├── az.js
│   │           │   │   ├── bg.js
│   │           │   │   ├── bn.js
│   │           │   │   ├── bs.js
│   │           │   │   ├── ca.js
│   │           │   │   ├── cs.js
│   │           │   │   ├── da.js
│   │           │   │   ├── de.js
│   │           │   │   ├── dsb.js
│   │           │   │   ├── el.js
│   │           │   │   ├── en.js
│   │           │   │   ├── es.js
│   │           │   │   ├── et.js
│   │           │   │   ├── eu.js
│   │           │   │   ├── fa.js
│   │           │   │   ├── fi.js
│   │           │   │   ├── fr.js
│   │           │   │   ├── gl.js
│   │           │   │   ├── he.js
│   │           │   │   ├── hi.js
│   │           │   │   ├── hr.js
│   │           │   │   ├── hsb.js
│   │           │   │   ├── hu.js
│   │           │   │   ├── hy.js
│   │           │   │   ├── id.js
│   │           │   │   ├── is.js
│   │           │   │   ├── it.js
│   │           │   │   ├── ja.js
│   │           │   │   ├── ka.js
│   │           │   │   ├── km.js
│   │           │   │   ├── ko.js
│   │           │   │   ├── lt.js
│   │           │   │   ├── lv.js
│   │           │   │   ├── mk.js
│   │           │   │   ├── ms.js
│   │           │   │   ├── nb.js
│   │           │   │   ├── ne.js
│   │           │   │   ├── nl.js
│   │           │   │   ├── pl.js
│   │           │   │   ├── ps.js
│   │           │   │   ├── pt-BR.js
│   │           │   │   ├── pt.js
│   │           │   │   ├── ro.js
│   │           │   │   ├── ru.js
│   │           │   │   ├── sk.js
│   │           │   │   ├── sl.js
│   │           │   │   ├── sq.js
│   │           │   │   ├── sr-Cyrl.js
│   │           │   │   ├── sr.js
│   │           │   │   ├── sv.js
│   │           │   │   ├── th.js
│   │           │   │   ├── tk.js
│   │           │   │   ├── tr.js
│   │           │   │   ├── uk.js
│   │           │   │   ├── vi.js
│   │           │   │   ├── zh-CN.js
│   │           │   │   └── zh-TW.js
│   │           │   ├── select2.full.js
│   │           │   └── select2.full.min.js
│   │           └── xregexp
│   │               ├── LICENSE.txt
│   │               ├── xregexp.js
│   │               └── xregexp.min.js
│   ├── css
│   │   ├── carouFredSel.css
│   │   ├── clear.css
│   │   ├── common.css
│   │   ├── font-awesome.min.css
│   │   ├── login_form.css
│   │   ├── sm-clean.css
│   │   └── style.css
│   ├── demo-images
│   │   ├── 01.jpg
│   │   ├── 01_blogpost_galery.jpg
│   │   ├── 02.jpg
│   │   ├── 02_blogpost_galery.jpg
│   │   ├── 03.jpg
│   │   ├── 03_blogpost_galery.jpg
│   │   ├── featured-imag1e.jpg
│   │   ├── featured-image.jpg
│   │   ├── one_drop_post_image02.jpg
│   │   └── profile_01.jpg
│   ├── etc
│   │   └── jido.jpg
│   ├── fonts
│   │   ├── FontAwesome.otf
│   │   ├── fontawesome-webfont.eot
│   │   ├── fontawesome-webfont.svg
│   │   ├── fontawesome-webfont.ttf
│   │   ├── fontawesome-webfont.woff
│   │   └── fontawesome-webfont.woff2
│   ├── images
│   │   ├── ajax-document-loader.gif
│   │   ├── arrow.png
│   │   ├── favicon.png
│   │   └── logo.png
│   ├── js
│   │   ├── custom_google_map_style.js
│   │   ├── html5.js
│   │   ├── imagesloaded.pkgd.js
│   │   ├── jquery.carouFredSel-6.0.0-packed.js
│   │   ├── jquery.easing.1.3.js
│   │   ├── jquery.js
│   │   ├── jquery.mousewheel.min.js
│   │   ├── jquery.nicescroll.min.js
│   │   ├── jquery.smartmenus.min.js
│   │   ├── jquery.touchSwipe.min.js
│   │   └── main.js
│   └── media
│       └── video.mp4
└── templates
    ├── admin
    │   └── base_site.html
    ├── base_generic.html
    ├── blog
    │   ├── post_detail.html
    │   ├── post_form.html
    │   ├── post_list.html
    │   └── post_video.html
    ├── index.html
    └── registration
        └── login.html
  • 05.22 배포 작업 후 기능 업데이트 작업 중 문제 사항 - settings.py 를 개발 / 운영 모드로 분리 작업 중 오류 발생

└ 추후 분리 작업 예정

Traceback (most recent call last):
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\core\management\base.py", line 328, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\core\management\commands\runserver.py", line 60, in execute
    super().execute(*args, **options)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\core\management\base.py", line 369, in execute
    output = self.handle(*args, **options)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\core\management\commands\runserver.py", line 67, in handle
    if not settings.DEBUG and not settings.ALLOWED_HOSTS:
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\conf\__init__.py", line 76, in __getattr__
    self._setup(name)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\conf\__init__.py", line 63, in _setup
    self._wrapped = Settings(settings_module)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\conf\__init__.py", line 142, in __init__
    mod = importlib.import_module(self.SETTINGS_MODULE)
  File "C:\Users\ankiwoong\AppData\Local\Programs\Python\Python37\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 965, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'config'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\core\management\__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\core\management\base.py", line 341, in run_from_argv
    connections.close_all()
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\db\utils.py", line 225, in close_all
    for alias in self:
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\db\utils.py", line 219, in __iter__
    return iter(self.databases)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\utils\functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\db\utils.py", line 153, in databases
    self._databases = settings.DATABASES
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\conf\__init__.py", line 76, in __getattr__
    self._setup(name)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\conf\__init__.py", line 63, in _setup
    self._wrapped = Settings(settings_module)
  File "C:\anjia.pythonanywhere.com\venv\lib\site-packages\django\conf\__init__.py", line 142, in __init__
    mod = importlib.import_module(self.SETTINGS_MODULE)
  File "C:\Users\ankiwoong\AppData\Local\Programs\Python\Python37\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 965, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'config'
  • 2020. 05. 26 disqus 설치 시 에러 발생 시 처리 방법

https://developer-ankiwoong.tistory.com/920

Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "C:\Python_kindergarten\venv\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "C:\Python_kindergarten\venv\lib\site-packages\django\core\management\__init__.py", line 377, in execute
    django.setup()
  File "C:\Python_kindergarten\venv\lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Python_kindergarten\venv\lib\site-packages\django\apps\registry.py", line 91, in populate
    app_config = AppConfig.create(entry)
  File "C:\Python_kindergarten\venv\lib\site-packages\django\apps\config.py", line 90, in create
    module = import_module(entry)
  File "C:\Users\ankiwoong\AppData\Local\Programs\Python\Python37\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked       
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module 
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "C:\Python_kindergarten\venv\lib\site-packages\disqus\__init__.py", line 3, in <module>
    from django.utils.six.moves.urllib.parse import urlencode
ModuleNotFoundError: No module named 'django.utils.six'

3.3.9 배포방법

  • 사용자 설정
git config --global user.name "아이디"
git config --global user.email 이메일주소
  • 깃 허브 연결
git clone 깃허브주소 프로젝트폴더
  • 프로젝트 폴더 이동
cd 프로젝트폴더
  • 파이썬 가상 환경 생성
virtualenv --python python3.6 venv
  • 가상 환경 진입
source /venv/bin/activate
  • 장고 설치
pip install django
  • Pillow 설치
pip install pillow
  • django-widget-tweaks 설치
django-widget-tweaks
  • 데이터베이스 초기화
python manage.py migrate
  • 관리자 계정 생성
python manage.py createsuperuser
  • 정적 파일 모으기
python manage.py collectstatic
  • static / media 서빙 설정

WEB > Static files: /static/ : static 경로 /media/ : media 경로

3.3.10 실행영상

  • 초기 버전 녹화
  • 수정 버전 녹화
  • 최종 버전 녹화

3.3.11 댓글

  • 김왼손: 안기웅님은 워낙 잘하셔서 제가 드릴 말씀이 없네요. :)

3.4 lee windRider

3.4.1 제목

스마트 팜

3.4.2 설명

스마트팜

  • 온도,습도센서에서 데이타를 받아 환기및 물주기를 하고 작물별 생육과정을 기록할수 있게 한다..
  • 스마트폰에서 원격으로 물주기및 환기를 할 수 있도록 한다.

3.4.3 코드

  • Main 화면파일 작성및 실행하기
  • MainGUI.py
# Main 화면파일 작성및 실행하기
main_form = uic.loadUiType("../GUI/Main.ui")[0]


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = MainGUI()
    mainWindow.show()
    app.exec_()


  • Serial 통신
  • MainGUI.py
    # SerialComm.py 의 RegisterReceiveCallback 함수를 호출하여 콜백함수 세팅및 Serial 통신 thread Start
    serialPort.RegisterReceiveCallback(self.OnReceiveSerialData) # 콜백함수(OnReceiveSerialData )에서 받은 메세지를 화면에 보여줌 
    t1 = threading.Thread(target=self.MainRhread, args=()) # 화면업데이트를 위한 Thread 생성
    t1.start()
  • SerialComm.py
    # 메세지를 받기위한 메소드
    def SerialReadlineThread(self):


    # 메세지를 보내기위한 메소드
    def Send(self, message, aSendCallback):

3.4.4 GitHub

https://github.com/kbntt/smartfarm.git

3.4.5 화면실행 영상

3.4.6 라즈베리파이에 라즈비안 설치

3.4.7 라즈베리파이에 Miniconda(anaconda) 설치

3.4.8 라즈베리파이에 git 설정

3.4.9 라즈베리파이에 카메라 설정

3.4.10 댓글

  • 김왼손: 아주 기대되는 프로그램 중 하나입니다. :)

3.5 ktkalpha

3.5.1 제목

코로나 2.0

3.5.2 설명

1. 게임 만들기, 2. gui가 있는 게임 만들기.

3.5.3 화면실행

Unknown.png

3.5.4 코드

#깃헙 봐주세요.
from bs4 import BeautifulSoup
from urllib.request import urlopen
import pyautogui
import time
n=[]

with urlopen('https://search.naver.com/search.naver?sm=tab_hty.top&where=nexearch&query=%ED%95%9C%EA%B5%AD%EC%BD%94%EB%A1%9C%EB%82%98+%ED%99%95%EC%A7%84%EC%9E%90&oquery=%ED%95%9C%EA%B5%AD%EC%BD%94%EB%A1%9C%EB%82%98+%ED%99%95%EC%A7%84%EC%9E%90+%EC%82%AC%EC%9D%B4%ED%8A%B8&tqi=UpzFgdprvmZsskp2GKdssssstRs-515551') as response:
    soup = BeautifulSoup(response, 'html.parser')
    for anchor in soup.find_all('strong', {'class' : 'num'}):
        n.append(anchor.get_text())   
while True:
    de=pyautogui.confirm(text="확진자 수="+n[0]+" 사망자 수="+n[3],buttons=['새로 고침','종료'])
    if de=='새로 고침':
        n=[]

        with urlopen('https://search.naver.com/search.naver?sm=tab_hty.top&where=nexearch&query=%ED%95%9C%EA%B5%AD%EC%BD%94%EB%A1%9C%EB%82%98+%ED%99%95%EC%A7%84%EC%9E%90&oquery=%ED%95%9C%EA%B5%AD%EC%BD%94%EB%A1%9C%EB%82%98+%ED%99%95%EC%A7%84%EC%9E%90+%EC%82%AC%EC%9D%B4%ED%8A%B8&tqi=UpzFgdprvmZsskp2GKdssssstRs-515551') as response:
            soup = BeautifulSoup(response, 'html.parser')
            for anchor in soup.find_all('strong', {'class' : 'num'}):
                n.append(anchor.get_text())
    if de=='종료':
        break

3.5.5 Github

https://github.com/ktkalpha

3.5.6 댓글

  • 김왼손: 오 동작이 잘 되네요. 멋집니다. :)

3.6 우유과자

3.6.1 제목

디코봇 만들기

3.6.2 설명

답변을 흡수해서 스스로 배우는 인공지능 챗봇을 만들고 싶습니다.

3.6.3 실행화면

실행화면을 넣어주세요.

3.6.4 현황

디스코드 봇으로 현재

  • 주사위 기능
  • 핑을 알려주는 기능
  • 안녕이라고 하면 답변하는 기능
  • 메아리 처럼 말을 따라하는 기능
  • 명령어 목록을 보여주는 기능
  • 원하는 상대가 봇인지 아닌지 밝혀주는 기능
  • 명령어를 잘못 입력하면 답변 해주는 기능
  • 키워드와 답변을 저장하는 기능
  • 키워드로 저장된 답변을 불러오는 기능
  • 저장되어 있는 키워드와 답변을 수정하는 기능
  • 저장되어 있는 키워드와 답변을 삭제하는 기능
  • 시공조아

3.6.5 코드

import discord  # 디스코드 모듈을 가져옴
from discord.ext import commands  # 디스코드 명령어들을 가져옴
import random # 랜덤 함수를 가져옴
import asyncio
import openpyxl # 엑셀파일을 열고 수정하는데 쓰임

bot = commands.Bot(command_prefix='!')  # 봇 접두사 예: !안녕
token = '봇 토큰' # 봇 토큰

@bot.event
async def on_ready(): # 준비가 되면 출력
    print('We have logged in as {0.user}'.format(bot))
    print("ready")
    game = discord.Game("열일") # ~하는중으로 상태에 뜸
    await bot.change_presence(status=discord.Status.online, activity=game)

@bot.command()
async def 안녕(ctx):
    a = str(ctx.author)[:-5]
    await ctx.send(f"안녕하세요, {a}님!") # 이게 되네 # 2시간 동안 난 왜 그 고생을...

@bot.command()
async def 테봇(ctx):
    await ctx.send("네! 테봇이에요!")
    await ctx.send("혹시 궁금한게 있으시다면 ``!명령어``를 쳐주세요!")

@bot.command()
async def (ctx):
    latency = bot.latency #핑을 알려줌
    await ctx.send(f'퐁! {round(latency * 1000)}ms')
    # latency값을 ms단위에 맞게 1000을 곱한후 round를 이용해 소수점 첫째자리 반올림, f-string 을 이용해 출력

@bot.command()
async def 주사위(ctx):
    roll = random.randint(1, 7)
    if roll in [2, 4, 5]:
        await ctx.send(f'{roll}가 나왔네요!')
    elif roll in [1, 3, 6]:
        await ctx.send(f'{roll}이 나왔어요!')
    else:
        msg = await ctx.send(f'{roll}이 나왔어요!(어라?)')
        await asyncio.sleep(1.0)
        await msg.edit(content='삐빗')

@bot.command()
async def 메아리(ctx, *, content: str):
        await ctx.send(content)

@bot.command()
async def (ctx, *, user: discord.User): # 봇 판정 코드
    name = user
    if user.bot == True:
        await ctx.send(f"{name}님은 봇입니다")
    elif user.bot == False:
        await ctx.send(f"{name}님은 사람입니다")

@bot.command()
async def 명령어(ctx):
    embed = discord.Embed(title="Test Bot2의 명령어 목록", description="명령어들은 아래에 나와있습니다.", color=0x62c1cc)
    embed.set_footer(text=".")
    embed.add_field(name="!안녕", value="간단한 인사입니다.", inline=False)
    embed.add_field(name="!핑", value="당신의 핑을 알려드려요.", inline=False)
    embed.add_field(name="!주사위", value="1~6중에 숫자가 나옵니다", inline=False)
    embed.add_field(name="!메아리 [문자열]", value="메아리가 울려 퍼지네요", inline=False)
    embed.add_field(name="!봇", value="!봇 '닉네임'으로 하면 그 상대가 봇인지 아닌지 알 수 있어요!", inline=False)
    embed.add_field(name="!학습", value="저장하고 싶은 값을 !학습 (키워드) (답)으로 적어주세요", inline=False)
    embed.add_field(name="기억", value="!학습으로 저장된 값을 -(키워드)로 불러올 수 있어요!", inline=False)
    embed.add_field(name="!수정", value="!학습으로 저장된 값을 !수정 (키워드) (답)으로 수정할 수 있어요!", inline=False)
    embed.add_field(name="!지워", value="!학습으로 저장된 값을 !지워 (키워드)로 지울 수 있어요!", inline=False)
    await ctx.send(embed=embed)




def learned(i, keyword): # 만약 시트에 같은 키워드가 적용되어 있다면 True를, 없다면 False를 리턴하는 함수
    file = openpyxl.load_workbook('memory.xlsx')
    sheet = file.active
    if sheet['A' + str(i)].value == keyword:
        return True
    else:
        return False

@bot.command()
async def 학습(ctx, *, content: str): # 키워드와 답변을 엑셀파일에 담는 커맨드
    file = openpyxl.load_workbook('memory.xlsx') # memory.xlsx라는 엑셀파일을 오픈 엑셀 파일 필요
    sheet = file.active # 엑셀파일 안에있는 값들을 불러와 저장
    learn = content.split(' ') # 키워드와 답변 분류
    if len(learn) > 1: # 형식 확인
        keyword = str(learn[0]) # 키워드는 맨 첫번째 단어
        answer = learn[1:] # 답변은 그 뒤에 모두
        for i in range(1, 101): # 엑셀에 남은 빈공간을 확인
            if learned(i, keyword): # 위에 있는 learned 함수에서 값을 받아 쓰는 구문
                await ctx.send("이미 존재하는 키워드 입니다!") # 값이 True 일때
                break
            else:
                if sheet['A' + str(i)].value == None: # 값이 False 일때 값이 들어 있지 않은 곳에 저장
                    sheet["A" + str(i)].value = keyword
                    sheet["B" + str(i)].value = " ".join(answer)
                    file.save('memory.xlsx') # 파일 세이브
                    await ctx.send("학습 완료 했습니다!") # 학습 완료 메세지
                    break
                elif i >= 100:
                    await ctx.send("저장할 수 있는 공간이 없어요!")
    else:
        await ctx.send("!학습 (키워드) (답)형식으로 해주세요!")

@bot.command()
async def 수정(ctx, *, content: str): # 값을 수정할 수 있는 함수 구조는 위에 !학습과 비슷
    file = openpyxl.load_workbook('memory.xlsx')
    sheet = file.active
    edit = content.split(' ')
    if len(edit) > 1:
        new_keyword = str(edit[0])
        new_answer = edit[1:]
        for i in range(1, 101):
            if learned(i, new_keyword):
                a = sheet['B' + str(i)].value
                sheet['B' + str(i)].value = None
                sheet['B' + str(i)].value = " ".join(new_answer)
                b = " ".join(new_answer)
                file.save('memory.xlsx')
                await ctx.send(f"{new_keyword} '{a}'(이)가 {new_keyword} '{b}'(으)로 수정되었어요!.")
                break
            elif i >= 100:
                await ctx.send("수정할 게 없네요. 그냥 저장하겠습니다.")
                await 학습(ctx, content=content) # !학습 함수를 불러와 저장
                break
    else:
        await ctx.send("!수정 (키워드) (답)형식으로 해주세요!")

@bot.command()
async def 지워(ctx, *, content: str):
    file = openpyxl.load_workbook('memory.xlsx')
    sheet = file.active
    delete = content.split(' ')
    if len(delete) < 2:
        del_keyword = str(delete[0])
        for i in range(1, 101):
            if learned(i, del_keyword):
                sheet['A' + str(i)].value = None
                sheet['B' + str(i)].value = None
                await ctx.send(f"{del_keyword}을(를) 성공적으로 지웠어요!")
                file.save('memory.xlsx')
                break
            elif i >= 100:
                await ctx.send(f"이 단어는 처음부터 없었는데요?")
                break
    else:
        await ctx.send("!지워 (키워드)형식으로 해주세요!")

@bot.event
async def on_message(message):
    await bot.process_commands(message) # 이벤트와 명령을 함께 쓸 수 있게 도와줌 (중요!!)
    if message.author.bot:
        return

    if "시공조아" in message.content:
        url = 'https://youtu.be/0GxIGaRsWW0' # 시공조아 유튜브 url
        embed = discord.Embed(title="시공조아", description="시공의 폭풍은 정말 최고야!", color=0x62c1cc) # 가사
        embed.add_field(name=" . ", value="시이공 조아 시이공", inline=False)
        embed.add_field(name=" . ", value="조아 시이이 공조아", inline=False)
        embed.add_field(name=" . ", value="히오스", inline=False)
        fixing_1 = discord.Embed(title='ERROR', description='ERROR FIXING.', color=0xFF0000)
        fixing_2 = discord.Embed(title='ERROR', description='ERROR FIXING..', color=0xFF0000)
        fixing_3 = discord.Embed(title='ERROR', description='ERROR FIXING...', color=0xFF0000)
        fixed = discord.Embed(title='ERROR FIXED', description='    ', color=0x62c1cc)
        msg = await message.channel.send(url)  # 고치기 위한 변수
        임베드 = await message.channel.send(embed=embed)
        await asyncio.sleep(31.0) # 영상 끝날 때까지 기다림
        await msg.delete() # 삭제
        for i in range(2):
            await 임베드.edit(embed=fixing_1)
            await asyncio.sleep(0.4)
            await 임베드.edit(embed=fixing_2)
            await asyncio.sleep(0.4)
            await 임베드.edit(embed=fixing_3)# embed 수정
            await asyncio.sleep(0.4)
        await 임베드.edit(content='삐빗', embed=fixed)

    if message.content.startswith("-"): # -(키워드) 형식으로 사용
        file = openpyxl.load_workbook('memory.xlsx')
        sheet = file.active
        memory = message.content.split("-") # -를 제외해서 저장되지 않게 함
        m = memory[1]
        for i in range(1, 101):
            if sheet['A' + str(i)].value == m: # 만약 키워드와 저장되어 있는 값이 같다면
                await message.channel.send(sheet["B" + str(i)].value) # 답변을 출력
                await mus(m)
                break
            elif i >= 101: # 만약 반복문의 끝에 도달한다면(한마디로 저장되어 있는 값이 없다면)
                await message.channel.send("존재하지 않는 값이에요;;") # 존재하지 않는 값입니다를 출력
                break

    if message.content.startswith("!"):
        split = message.content.split(" ")
        check = split[0][1:]
        command_list = ['메아리', '안녕', '주사위', '핑', '학습', '수정', '지워', '테봇', '명령어', '봇']
        if len(check) < 1:
            await message.channel.send("불렀어요?")
        elif check not in command_list:
            a = random.randint(1, 3)
            if a == 1:
                await message.channel.send("잘 못들었어요!")
            elif a == 2:
                await message.channel.send("뭐라구요?")
            elif a == 3:
                await message.channel.send("잘 모르시겠을 때는 ``!명령어``를 쳐주세요!")

bot.run(token)  # 실행

3.6.6 댓글

  • 김왼손: 와.. 챗봇 완성되면 저도 한번 사용해보고 싶네요. :)

3.7 한정우

3.7.1 제목

제목을 정해주세요.

3.7.2 설명

계산기 프로그램을 tkinter모듈을 사용해 클릭가능하게 만들고 싶습니다.

3.7.3 실행화면

실행화면을 넣어주세요.

3.7.4 github

https://github.com/python

3.7.5 댓글

  • 김왼손: 기대하고 있겠습니다. :)