본문으로 건너뛰기

Python Django 요약 (내가 보려고 만든)

Dev Python Django
thumbnail

Python Django를 공부하며 기록해둔 것들을 포스팅합니다.

실무에서 바로 사용할 수 있도록 기록하였습니다.


⭐ MTV 패턴
#

MTV Pattern

  • Model : DB와의 상호작용을 담당하며 데이터의 구조를 정의
  • Template : 사용자에게 보여지는 HTML 등의 출력물을 생성
  • View : 비즈니스 로직을 처리하고 Model과 Template 간의 연결을 관리

⭐ 설치
#

프로젝트 : myblog

앱(서비스) : post

1. venv 세팅
#

# .venv 외 원하는 이름 사용 가능
python3 -m venv .venv
source .venv/bin/activate

2. Django 설치
#

venv 활성화 상태

pip install django~=3.2.10

3. 프로젝트 생성
#

myblog 프로젝트 디렉토리가 생성됩니다.

django-admin startproject myblog .

4. 앱 추가
#

post 디렉토리가 생성됩니다.

python manage.py startapp mypost

5. 앱 시작
#

python manage.py runserver

⭐ 설정
#

1. [ myblog/settings.py ]
#

앱 등록
#

생성한 앱을 INSTALLED_APPS 에 등록해주어야 정상 작동합니다.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'mypost' # 앱 추가
]
...
TIME_ZONE = 'Asia/Seoul' # 시간대 한국으로 변경

디버깅 모드 설정
#

배포 시에는 False로 설정해야 합니다. (에러 내용 노출 방지)

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

접근 제한 설정
#

허용 가능한 호스트는 운영 서버 등에 배포하여, 서비스할 때 호스트로 사용 가능한 호스트 또는 도메인 목록입니다.

위 DEBUG 설정이 True 이고 ALLOWED_HOSTS 설정 값이 비어있으면 [’.localhost’, ‘127.0.0.1’, ‘[::1]’] 대상에 대해 유효성을 검증합니다.

ALLOWED_HOSTS = []

2. [ myblog/urls.py ]
#

각 앱에 경로를 할당합니다. (아래는 기본 값)

urlpatterns = [
    path('admin/', admin.site.urls),
]

3. 어드민 모델 마이그레이션
#

어드민 기능을 사용하려면 필수 사항입니다.

python manage.py migrate

4. 어드민 계정 생성
#

python manage.py createsuperuser
# pw: 1q2w3e4r! (임의 값)

⭐ Model
#

앱의 모델 생성
#

📄 mypost/models.py

class Mypost(models.Model):
    title = models.CharField(max_length=300)
    tag = models.CharField(max_length=100)
    image = models.CharField(max_length=300)
    summary = models.TextField()
    content = models.TextField()
# 정의한 모델을 이용하여 DB 생성
python manage.py makemigrations
python manage.py migrate

앱 모델을 어드민 페이지에 적용
#

📄 myblog/admin.py

from django.contrib import admin
from .models import Mypost

admin.site.register(Mypost)

⭐ Template
#

📄 mypost/templates/mypost/postlist.html

<html>
    <head>
        <title>My blog</title>
    </head>
    <body>
        <h1><a href="">Post list</a></h1>
        <section>
<!-- posts라는 변수에 담긴 데이터(일반적으로 뷰에서 제공된 포스트 목록)를 반복함 -->
            {% for post in posts %}
            <div>
<!-- 각 post 객체에 포함된 이미지 경로를 출력하고, 이미지의 제목과 크기를 설정 -->
		            <img src="{{ post.image }}" alt="{{ post.title }}" width="300" />
                
                <h2>
<!-- 각 post의 세부 페이지로 이동하는 링크를 생성 -->
<!-- {% url 'post_detail' pk=post.pk %}는 'post_detail'이라는 이름의 URL에 post의 pk 값을 전달하여 세부 페이지로 연결 -->
                    <a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a>
                </h2>
<!-- 각 post의 태그를 출력 -->
                <p>Tags : {{ post.tag }}</p>
<!-- 각 post의 요약(summary)을 출력 -->
                <p>Summary : {{ post.summary }}</p>
            </div>
            {% endfor %}
        </section>
    </body>
</html>
  1. {% for post in posts %} ... {% endfor %}
    • posts는 뷰에서 템플릿으로 전달된 컨텍스트 변수로, 여러 개의 포스트 객체를 포함하고 있습니다.
    • for 루프는 posts 리스트 내의 각 post 객체를 반복하며, 해당 객체의 정보를 HTML로 렌더링합니다.
  2. {% for post in posts %} ... {% endfor %}
    • posts는 뷰에서 템플릿으로 전달된 컨텍스트 변수로, 여러 개의 포스트 객체를 포함하고 있습니다.
    • for 루프는 posts 리스트 내의 각 post 객체를 반복하며, 해당 객체의 정보를 HTML로 렌더링합니다.
  3. <a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a>
    • {% url %} 태그는 주어진 뷰 이름에 해당하는 URL을 생성합니다.
    • 'post_detail'은 URL 패턴 이름입니다. urls.py 파일에서 정의된 이름을 사용합니다.
      • 예를 들어 urls.py 파일에서 path('post/<int:pk>/', views.post_detail, name='post_detail')와 같이 정의된 경우, post_detail 이름을 사용하여 해당 URL을 참조할 수 있습니다.
      • pk라는 URL 파라미터는 urls.pyviews.py에서 정수(<int:pk>)로 지정되어 있으며, 템플릿에서 pk=post.pk로 전달된 값이 이 자리에 들어가게 됩니다.
      • pk=post.pk: 포스트 객체의 Primary Key인 pk를 해당 URL 패턴에 전달하여, 특정 포스트의 세부 정보를 조회할 수 있도록 URL을 생성합니다.

⭐ View
#

📄 mypost/forms.py

from django import forms
from .models import Mypost

class MypostForm(forms.ModelForm):
    # Meta 클래스는 폼에 대한 메타데이터를 정의하는 내부 클래스
    class Meta:
        # 사용할 모델을 Mypost로 지정
        model = Mypost
        # 폼에서 사용자에게 입력받을 필드를 나열
        fields = ('title', 'tag', 'image', 'summary', 'content')
  • MypostForm 클래스ModelForm을 상속받아 Django의 모델과 연관된 폼을 생성합니다. 여기서는 Mypost 모델을 기반으로 사용자가 title, tag, image, summary, content 필드를 입력할 수 있는 폼을 정의합니다.
  • ModelForm은 폼에서 입력받은 데이터를 바로 모델 인스턴스에 매핑하고, 저장할 수 있는 기능을 제공합니다.
  • fields에 나열된 필드들만 사용자로부터 입력받을 수 있도록 폼에 포함됩니다.

📄 mypost/views.py

from django.shortcuts import render, redirect
from .models import Mypost 
from .forms import MypostForm

# 1. 게시물 목록을 보여주는 뷰 함수
def post_list(request):
    # Mypost 모델의 모든 객체를 가져와서 'posts' 변수에 저장
    posts = Mypost.objects.all()
    
    # 'posts' 데이터를 'mypost/post_list.html' 템플릿에 전달하고 렌더링
    return render(request, 'mypost/post_list.html', {'posts': posts})

# 2. 게시물 상세 정보를 보여주는 뷰 함수
def post_detail(request, pk):
    # 주어진 pk(Primary Key)를 사용하여 특정 Mypost 객체를 가져옴
    post = Mypost.objects.get(id=pk)
    
    # 'post' 객체를 'mypost/post_detail.html' 템플릿에 전달하여 렌더링
    return render(request, 'mypost/post_detail.html', {'post': post})

# 3. 게시물을 업로드하는 뷰 함수
def post_upload(request):
    # 3-1. 사용자가 폼을 제출한 경우 (POST 요청)
    if request.method == "POST":
        # 제출된 데이터를 바탕으로 MypostForm 인스턴스 생성
        form = MypostForm(request.POST)
        
        # 폼 데이터가 유효한지 확인
        if form.is_valid():
            # 폼 데이터를 저장하되, 바로 데이터베이스에 커밋하지 않고 인스턴스만 반환
            post = form.save(commit=False)
            
            # 필요한 추가 처리를 한 후 데이터베이스에 저장
            post.save()
            
            # 새로 생성된 게시물의 상세 페이지로 리디렉션
            return redirect('post_list', pk=post.pk)
    
    # 3-2. GET 요청인 경우 (사용자가 페이지에 처음 접근한 경우)
    else:
        # 빈 MypostForm 인스턴스를 생성하여 사용자에게 보여줌
        form = MypostForm()
    
    # 빈 폼 또는 제출된 폼을 'mypost/post_upload.html' 템플릿에 전달하여 렌더링
    return render(request, 'mypost/post_upload.html', {'form': form})
...
  • post_list 함수
    • 역할: Mypost 모델의 모든 게시물을 데이터베이스에서 조회하고, 이를 템플릿으로 전달하여 게시물 목록을 출력하는 역할을 합니다.
    • 작동 방식
      • Mypost.objects.all()을 통해 모든 게시물을 가져옵니다.
      • render() 함수를 사용해 post_list.html 템플릿을 렌더링하고, 게시물 데이터를 posts로 전달합니다.
  • post_detail 함수
    • 역할: 주어진 pk 값으로 특정 게시물의 세부 정보를 조회하고, 해당 데이터를 템플릿에 전달하여 상세 페이지를 보여줍니다.
    • 작동 방식
      • Mypost.objects.get(id=pk)로 주어진 pk에 해당하는 게시물을 조회합니다.
      • 조회된 게시물 객체를 post_detail.html 템플릿에 전달하여 렌더링합니다.
  • post_upload 함수
    • 역할: 새로운 게시물을 작성하여 업로드하는 뷰입니다. GET 요청일 때는 빈 폼을 보여주고, POST 요청일 때는 폼 데이터를 받아 게시물을 저장합니다.
    • 작동 방식
      • POST 요청: 사용자가 게시물 작성 폼을 제출하면, MypostForm을 통해 폼 데이터를 받아서 유효성 검사를 수행합니다. 검사가 통과하면 form.save(commit=False)로 폼 데이터를 바탕으로 게시물 객체를 생성하되, 데이터베이스에 바로 저장하지 않고, 추가 처리를 한 후 저장합니다.
      • GET 요청: 사용자가 페이지를 처음 열면 빈 폼을 렌더링합니다.
      • 성공적으로 저장된 후에는, 해당 게시물의 상세 페이지로 리디렉션됩니다.