📌 Django 워크플로우: (CRUD 기능과 로그인 기능까지) 🛠️
이 워크플로우는 Django 프로젝트를 시작하는 단계부터 기본적인 로그인 기능과 CRUD(Create, Read, Update, Delete) 기능을 구현하는 단계를 상세하게 안내하며, 각 코드 블록에 주석을 추가하여 코드의 이해도를 높입니다.
1. 프로젝트 및 앱 생성 🚀
- 프로젝트 생성: Django 프로젝트는 웹 애플리케이션의 전체 설정을 담고 있는 컨테이너입니다.
django-admin startproject myproject cd myproject - 앱 생성: 앱은 프로젝트 내에서 특정 기능을 담당하는 모듈입니다. 예를 들어, 블로그 앱, 사용자 관리 앱 등이 있습니다.
python manage.py startapp blog python manage.py startapp accounts settings.py설정:myproject/settings.py파일에 생성한 앱을INSTALLED_APPS목록에 추가합니다.# myproject/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog', # blog 앱 추가 'accounts', # accounts 앱 추가 ]
2. 사용자 모델 및 인증 설정 🔒
- 사용자 모델 정의 (accounts 앱): Django의 기본 사용자 모델(
auth.User)을 사용하거나, 커스텀 사용자 모델을 정의할 수 있습니다. 커스텀 사용자 모델을 정의하려면accounts/models.py파일에AbstractUser또는AbstractBaseUser를 상속받은 모델을 정의해야 합니다.
# accounts/models.py
from django.contrib.auth.models import AbstractUser
class User(AbstractUser): pass # 기본 사용자 모델을 확장하지 않고 그대로 사용
- 커스텀 사용자 모델 설정:
myproject/settings.py파일에 커스텀 사용자 모델을 사용하도록 설정합니다.
# myproject/settings.py
AUTH_USER_MODEL = 'accounts.User' # 커스텀 사용자 모델 사용 설정
- 마이그레이션: 데이터베이스에 사용자 모델을 반영하기 위해 마이그레이션을 수행합니다
python manage.py makemigrations accounts # 마이그레이션 파일 생성
python manage.py migrate accounts # 데이터베이스에 마이그레이션 적용
- 로그인, 로그아웃 템플릿 생성:
accounts앱의templates디렉토리에 로그인 및 로그아웃 템플릿(login.html,logout.html)을 생성합니다. - 로그인, 로그아웃 기능 구현:
accounts앱의views.py파일에 로그인 및 로그아웃 기능을 구현합니다.
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import AuthenticationForm
def login_view(request):
# POST 요청 시 로그인 처리
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST) # 로그인 폼 생성
if form.is_valid(): # 폼 유효성 검사
username = form.cleaned_data.get('username') # 폼 데이터에서 사용자 이름 가져오기
password = form.cleaned_data.get('password') # 폼 데이터에서 비밀번호 가져오기
user = authenticate(username=username, password=password) # 사용자 인증
if user is not None: # 사용자 인증 성공 시
login(request, user) # 사용자 로그인 처리
return redirect('blog:post_list') # 블로그 메인 페이지로 이동
else:
return render(request, 'accounts/login.html', {'form': form, 'error': '로그인 실패'}) # 로그인 실패 시 오류 메시지 전달
# GET 요청 시 로그인 폼 보여주기
else:
form = AuthenticationForm() # 빈 로그인 폼 생성
return render(request, 'accounts/login.html', {'form': form}) # 로그인 폼 렌더링
def logout_view(request):
logout(request) # 사용자 로그아웃 처리
return redirect('accounts:login') # 로그아웃 후 로그인 페이지로 이동
- URL 설정 (accounts 앱):
accounts/urls.py파일을 생성하고 로그인 및 로그아웃 URL을 설정합니다.myproject/urls.py파일에 해당 URL을 포함합니다.# myproject/urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), # 관리자 페이지 URL 설정 path('accounts/', include('accounts.urls')), # accounts 앱 URL 포함 path('blog/', include('blog.urls')), # blog 앱 URL 추가 ] # accounts/urls.py from django.urls import path from . import views app_name = 'accounts' urlpatterns = [ path('login/', views.login_view, name='login'), # 로그인 URL 패턴 설정 path('logout/', views.logout_view, name='logout'), # 로그아웃 URL 패턴 설정 ]- 템플릿 설정: 템플릿에서 로그인, 로그아웃 폼과 버튼을 생성하고, 로그인 상태에 따라 메뉴 등을 다르게 보여줄 수 있도록 설정합니다.
3. 모델 정의 (blog 앱) 📝
- 모델 설계: 블로그 게시글을 저장할 모델(
Post)을blog/models.py파일에 정의합니다.ForeignKey를 사용하여 사용자 모델과 연결할 수 있습니다.
from django.conf import settings
from django.db import models
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) # 작성자 ForeignKey 설정
title = models.CharField(max_length=200) # 게시글 제목 필드
content = models.TextField() # 게시글 내용 필드
created_at = models.DateTimeField(auto_now_add=True) # 게시글 생성 시간 필드 (자동 설정)
updated_at = models.DateTimeField(auto_now=True) # 게시글 수정 시간 필드 (자동 설정)
def __str__(self):
return self.title # 게시글 제목으로 객체 표현
- 마이그레이션: 데이터베이스에 모델을 반영하기 위해 마이그레이션을 수행합니다.
# blog 앱에 대한 마이그레이션 파일 생성
python manage.py makemigrations blog
# 데이터베이스에 blog 앱 마이그레이션 적용
python manage.py migrate blog
4. CRUD 기능 구현 (blog 앱) ⚙️
- 폼 생성 (blog 앱):
blog/forms.py파일에 게시글 생성 및 수정을 위한 폼을 생성합니다.
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
# 모델 폼 상속
class Meta:
model = Post # 사용할 모델 지정
fields = ['title', 'content'] # 폼에 포함할 필드 지정
- 뷰 구현 (blog 앱):
blog/views.py파일에 게시글 목록, 상세 보기, 생성, 수정, 삭제 기능을 구현합니다.@login_required데코레이터: 로그인한 사용자만 해당 기능에 접근할 수 있도록 합니다.
from django.shortcuts import render, redirect, get_object_or_404
from .models import Post
from .forms import PostForm
from django.contrib.auth.decorators import login_required # 로그인 데코레이터 임포트
def post_list(request):
posts = Post.objects.all() # 모든 게시글 가져오기
return render(request, 'blog/post_list.html', {'posts': posts}) # 게시글 목록 템플릿 렌더링
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk) # 특정 pk의 게시글 가져오기 (없으면 404 에러)
return render(request, 'blog/post_detail.html', {'post': post}) # 게시글 상세 템플릿 렌더링
@login_required # 로그인한 사용자만 접근 가능
def post_create(request):
# POST 요청 시 게시글 생성
if request.method == 'POST':
form = PostForm(request.POST) # 폼 데이터로 PostForm 생성
if form.is_valid(): # 폼 유효성 검사
post = form.save(commit=False) # 게시글 저장 (커밋은 보류)
post.author = request.user # 게시글 작성자 설정 (현재 로그인 사용자)
post.save() # 게시글 저장 완료
return redirect('blog:post_detail', pk=post.pk) # 게시글 상세 페이지로 리디렉션
# GET 요청 시 폼 보여주기
else:
form = PostForm() # 빈 폼 생성
return render(request, 'blog/post_form.html', {'form': form}) # 게시글 생성 폼 렌더링
@login_required # 로그인한 사용자만 접근 가능
def post_update(request, pk):
post = get_object_or_404(Post, pk=pk) # 수정할 게시글 가져오기 (없으면 404 에러)
# POST 요청 시 게시글 수정
if request.method == 'POST':
form = PostForm(request.POST, instance=post) # 폼 데이터로 PostForm 생성 (instance에 기존 게시글 설정)
if form.is_valid(): # 폼 유효성 검사
form.save() # 게시글 저장
return redirect('blog:post_detail', pk=post.pk) # 게시글 상세 페이지로 리디렉션
# GET 요청 시 폼 보여주기
else:
form = PostForm(instance=post) # 기존 게시글로 채워진 폼 생성
return render(request, 'blog/post_form.html', {'form': form}) # 게시글 수정 폼 렌더링
@login_required # 로그인한 사용자만 접근 가능
def post_delete(request, pk):
post = get_object_or_404(Post, pk=pk) # 삭제할 게시글 가져오기 (없으면 404 에러)
post.delete() # 게시글 삭제
return redirect('blog:post_list') # 게시글 목록 페이지로 리디렉션
- URL 설정 (blog 앱):
blog/urls.py파일을 생성하고, 각 뷰 함수에 해당하는 URL 패턴을 정의합니다.myproject/urls.py파일에 해당 URL을 포함합니다.# myproject/urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), # 관리자 페이지 URL 설정 path('accounts/', include('accounts.urls')), # accounts 앱 URL 포함 path('blog/', include('blog.urls')), # blog 앱 URL 포함 ]
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.post_list, name='post_list'), # 게시글 목록 URL 패턴 설정
path('<int:pk>/', views.post_detail, name='post_detail'), # 게시글 상세 URL 패턴 설정
path('create/', views.post_create, name='post_create'), # 게시글 생성 URL 패턴 설정
path('<int:pk>/update/', views.post_update, name='post_update'), # 게시글 수정 URL 패턴 설정
path('<int:pk>/delete/', views.post_delete, name='post_delete'), # 게시글 삭제 URL 패턴 설정
]
5. 템플릿 생성 (blog 앱) 🖼️
- 템플릿 파일 생성:
blog/templates/blog디렉토리에post_list.html,post_detail.html,post_form.html템플릿 파일을 생성합니다. - 템플릿 구성 (예시):
post_list.html(게시글 목록 템플릿):- 설명:
{% for post in posts %}: 템플릿 변수posts에 담긴 게시글 객체들을 반복하여 출력합니다.{{ post.title }}: 게시글 제목을 출력합니다.{{ post.author.username }}: 게시글 작성자의 사용자 이름을 출력합니다.{% url 'blog:post_detail' pk=post.pk %}:blog앱의post_detailURL 패턴에 게시글의pk값을 전달하여 상세 페이지 링크를 생성합니다.{% url 'blog:post_create' %}:blog앱의post_createURL 패턴으로 이동하는 링크를 생성합니다.{% url 'blog:post_update' pk=post.pk %}:blog앱의post_updateURL 패턴에 게시글의pk값을 전달하여 수정 페이지 링크를 생성합니다.{% url 'blog:post_delete' pk=post.pk %}:blog앱의post_deleteURL 패턴에 게시글의pk값을 전달하여 삭제 페이지 링크를 생성합니다.
- 설명:
<!DOCTYPE html>
<html>
<head>
<title>게시글 목록</title>
</head>
<body>
<h1>게시글 목록</h1>
<ul>
{% for post in posts %}
<li>
<a href="{% url 'blog:post_detail' pk=post.pk %}">{{ post.title }}</a> (작성자: {{ post.author.username }})
<a href="{% url 'blog:post_update' pk=post.pk %}">수정</a>
<a href="{% url 'blog:post_delete' pk=post.pk %}">삭제</a>
</li>
{% endfor %}
</ul>
<a href="{% url 'blog:post_create' %}">새 게시글 작성</a>
</body>
</html>
-
post_detail.html(게시글 상세 템플릿):- 설명:
{{ post.title }}: 게시글 제목을 출력합니다.{{ post.content }}: 게시글 내용을 출력합니다.{{ post.author.username }}: 게시글 작성자의 사용자 이름을 출력합니다.{{ post.created_at }}: 게시글 생성 시간을 출력합니다.{{ post.updated_at }}: 게시글 수정 시간을 출력합니다.{% url 'blog:post_update' pk=post.pk %}:blog앱의post_updateURL 패턴에 게시글의pk값을 전달하여 수정 페이지 링크를 생성합니다.{% url 'blog:post_delete' pk=post.pk %}:blog앱의post_deleteURL 패턴에 게시글의pk값을 전달하여 삭제 페이지 링크를 생성합니다.{% url 'blog:post_list' %}:blog앱의post_listURL 패턴으로 이동하는 목록 페이지 링크를 생성합니다.
- 설명:
<!DOCTYPE html>
<html>
<head>
<title>{{ post.title }}</title>
</head>
<body>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<p>작성자: {{ post.author.username }}</p>
<p>작성일: {{ post.created_at }}</p>
<p>수정일: {{ post.updated_at }}</p>
<a href="{% url 'blog:post_update' pk=post.pk %}">수정</a>
<a href="{% url 'blog:post_delete' pk=post.pk %}">삭제</a>
<a href="{% url 'blog:post_list' %}">목록으로</a>
</body>
</html>
post_form.html(게시글 생성/수정 폼 템플릿):- 설명:
{% csrf_token %}: CSRF 공격 방지 토큰을 포함합니다.{{ form.as_p }}: 폼 필드를p태그로 감싸서 출력합니다. (다른 렌더링 옵션도 사용 가능)<button type="submit">저장</button>: 폼 제출 버튼입니다.{% url 'blog:post_list' %}:blog앱의post_listURL 패턴으로 이동하는 목록 페이지 링크를 생성합니다.
- 설명:
```html
<!DOCTYPE html>
<html>
<head>
<title>로그인</title>
</head>
<body>
<h1>로그인</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
{% if error %}
<p style="color:red">{{ error }}</p>
{% endif %}
<button type="submit">로그인</button>
</form>
</body>
</html>
```
* **설명:**
* `{% csrf_token %}`: CSRF 공격 방지 토큰을 포함합니다.
* `{{ form.as_p }}`: 로그인 폼 필드를 `p` 태그로 감싸서 출력합니다.
* `{% if error %}`: 로그인 실패 시 에러 메세지를 출력합니다.
* `<button type="submit">로그인</button>`: 폼 제출 버튼입니다.
- *로그인 템플릿 (accounts 앱): `accounts/templates/accounts` 디렉토리에 `login.html` 템플릿 파일을 생성합니다.
- 로그아웃 템플릿 (accounts 앱):
accounts/templates/accounts디렉토리에logout.html템플릿 파일을 생성합니다.- 설명:
- 로그아웃 완료 메세지를 출력하고 로그인 페이지로 이동하는 링크를 제공합니다.
- 설명:
<!DOCTYPE html>
<html>
<head>
<title>로그아웃</title>
</head>
<body>
<h1>로그아웃 되었습니다.</h1>
<a href="{% url 'accounts:login' %}">다시 로그인하기</a>
</body>
</html>
6. 테스트 및 디버깅 🧪
- Django 개발 서버 실행:
python manage.py runserver - 기능 테스트: 웹 브라우저를 통해 로그인, 로그아웃, 게시글 목록, 상세 보기, 생성, 수정, 삭제 기능을 테스트합니다.
- 디버깅: 코드에 오류가 있으면, 오류 메시지를 확인하고 코드를 수정합니다.
7. 추가 기능 구현 (선택 사항) ✨
- 페이지네이션: 게시글 목록 페이지에 페이지네이션을 추가하여 게시글이 많을 때 효율적으로 관리할 수 있도록 합니다.
- 검색 기능: 게시글 제목이나 내용으로 게시글을 검색할 수 있도록 합니다.
- 권한 관리: 특정 사용자에게만 게시글을 생성, 수정, 삭제 권한을 부여합니다.
- CSS 적용: 웹 페이지에 스타일을 적용하여 디자인을 개선합니다.
'Python > Django' 카테고리의 다른 글
| 관계형 데이터베이스 보충 (3) | 2025.01.09 |
|---|---|
| Django AUTH USER 사용자 모델 (2) | 2025.01.08 |
| 다대다 관계 보충설명 (7) | 2025.01.08 |
| [TIL] ForeignKey 보충 (코드예시) (0) | 2025.01.08 |
| [TIL] Django Model, foreignkey와 migration (0) | 2025.01.07 |