์๋ ํ์ธ์! ์น ๊ฐ๋ฐ์ ์ธ๊ณ์ ์ค์ ์ฌ๋ฌ๋ถ์ ํ์ํฉ๋๋ค. ํ์ด์ฌ์ ๊ฐ๋ ฅํ ์น ํ๋ ์์ํฌ์ธ Django๋ ๋ณต์กํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ฝ๊ณ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ ์ ์๋๋ก ๋์์ค๋๋ค. ํนํ, ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ํต์ฌ ๊ธฐ๋ฅ์ธ ๋ฐ์ดํฐ๋ฅผ **์์ฑ(Create), ์ฝ๊ธฐ(Read), ์์ (Update), ์ญ์ (Delete)**ํ๋ 4๊ฐ์ง ๊ธฐ๋ณธ ์์ , ์ฆ CRUD๋ ๋ฐ์ดํฐ ๊ด๋ฆฌ์ ์ํ์ด์ ์ค๋ฉ๊ฐ๋ผ๊ณ ํ ์ ์์ต๋๋ค.
์ด ๊ฐ์ด๋์์๋ Django๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๋ค๋ฃจ๋ CRUD์ ์๋ฆฌ์ ๋ฐฉ๋ฒ์ ์ด๋ณด์๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ๋จ๊ณ๋ณ๋ก ์ค๋ช ํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
1. ๐ CRUD๋ ๋ฌด์์ธ๊ฐ์? (Create, Read, Update, Delete)
CRUD๋ ๋๋ถ๋ถ์ ์ํํธ์จ์ด ์ ํ๋ฆฌ์ผ์ด์ ์์ ์๊ตฌ๋๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ ๋ํ๋ด๋ ์ฝ์ด์ ๋๋ค.
| ์ฝ์ | ํ๋ค์ | ๊ธฐ๋ฅ | Django์์์ ์ญํ |
| C | Create | ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ์์ ์์ฑํฉ๋๋ค. | ์ฌ์ฉ์ ์
๋ ฅ(Form)์ ๋ฐ์ Model ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ save() ๋๋ create() ๋ฉ์๋๋ก DB์ ์ ์ฅํฉ๋๋ค. |
| R | Read | ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๊ณ ๊ฐ์ ธ์ต๋๋ค. | Model.objects.all(), get(), filter() ๋ฑ์ ๋ฉ์๋๋ก DB์์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ต๋๋ค. |
| U | Update | ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ์์ ํฉ๋๋ค. | ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ ๊ฐ์ ๋ณ๊ฒฝํ ํ, save() ๋ฉ์๋๋ก DB์ ๋ฐ์ํฉ๋๋ค. |
| D | Delete | ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ์์์ ์ญ์ ํฉ๋๋ค. | ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ delete() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ DB์์ ์ ๊ฑฐํฉ๋๋ค. |
Django๋ **ORM (Object-Relational Mapping)**์ด๋ผ๋ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ, ๋ณต์กํ SQL ์ฟผ๋ฆฌ ๋์ ํ์ด์ฌ ์ฝ๋๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ค๋ฃฐ ์ ์๊ฒ ํด์ค๋๋ค. ์ด ORM์ ํตํด ์ฐ๋ฆฌ๋ Model์ด๋ผ๋ ๊ฐ๋ ์ ์ฌ์ฉํ์ฌ CRUD ์์ ์ ์ํํฉ๋๋ค.
2. ๐งฑ ๋ฐ์ดํฐ ๋ชจ๋ธ(Model) ์ ์ํ๊ธฐ
CRUD ์์
์ ์์ํ๊ธฐ ์ ์, ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ง ์ ์ํด์ผ ํฉ๋๋ค. Django์์ ์ด ์ ์๋ models.py ํ์ผ์ ํ์ด์ฌ ํด๋์ค ํํ๋ก ์์ฑํฉ๋๋ค.
์๋ฅผ ๋ค์ด, ๊ฐ๋จํ Todo ๋ฆฌ์คํธ ์ฑ์ ๋ง๋ ๋ค๊ณ ๊ฐ์ ํ๊ณ , ํ ์ผ์ **์ ๋ชฉ(title)**๊ณผ **์๋ฃ ์ฌ๋ถ(completed)**๋ฅผ ์ ์ฅํ๋ ๋ชจ๋ธ์ ๋ง๋ค์ด ๋ด ์๋ค.
#
# crudapp/models.py
from django.db import models
class Todo(models.Model):
# ํ ์ผ์ ์ ๋ชฉ (์ต๋ 200์)
title = models.CharField(max_length=200)
# ์๋ฃ ์ฌ๋ถ (True/False)
completed = models.BooleanField(default=False)
# ๊ฐ์ฒด๋ฅผ ์ฌ๋์ด ์ฝ๊ธฐ ์ฝ๊ฒ ํํํ๊ธฐ ์ํ ๋ฉ์๋
def __str__(self):
return self.title
์ด ์ฝ๋๋ฅผ ์์ฑํ ํ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ด ๊ตฌ์กฐ๋ฅผ ๋ฐ์ํ๊ธฐ ์ํด ๋ค์ ๋ ๊ฐ์ง ๋ช ๋ น์ด($$)๋ฅผ ํฐ๋ฏธ๋์ ์ ๋ ฅํด์ผ ํฉ๋๋ค.
python manage.py makemigrationspython manage.py migrate
3. ✅ CRUD ํต์ฌ ๊ธฐ๋ฅ ๊ตฌํ (Views์์ ORM ์ฌ์ฉ)
์ด์ views.py ํ์ผ์์ ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ 4๊ฐ์ง CRUD ์์
์ Django ORM์ ์ด์ฉํด ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
3.1. ๐ ์์ฑ (Create)
์๋ก์ด Todo ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํฉ๋๋ค. create() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด ์์ฑ๊ณผ ์ ์ฅ ๊ณผ์ ์ ํ ๋ฒ์ ์ฒ๋ฆฌํ ์ ์์ด ํธ๋ฆฌํฉ๋๋ค.
# crudapp/views.py - ์ผ๋ถ
from .models import Todo
def create_todo(request):
# ์ค์ ๋ก๋ ์ฌ์ฉ์๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์์ผ ํฉ๋๋ค. (์: request.POST)
if request.method == 'POST':
# title ํ๋์ '์๋ก์ด ํ ์ผ'์ด๋ผ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ค๊ณ ๊ฐ์
new_title = request.POST.get('title')
# 1. create() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์์ฑ ๋ฐ ์ ์ฅ
Todo.objects.create(
title=new_title,
completed=False
)
# ์ ์ฅ์ด ์๋ฃ๋๋ฉด ๋ชฉ๋ก ํ์ด์ง๋ก ์ด๋
return redirect('list_url')
# ... (ํ
ํ๋ฆฟ ๋ ๋๋ง ์ฝ๋)
๋ค๋ฅธ ์์ฑ ๋ฐฉ๋ฒ:
save()๋ฉ์๋
new_task = Todo(title=new_title, completed=False)(๊ฐ์ฒด ์์ฑ)
new_task.save()(DB์ ์ ์ฅ)์ด ๋ฐฉ๋ฒ์ ๊ฐ์ฒด๋ฅผ ๋จผ์ ๋ฉ๋ชจ๋ฆฌ์ ์์ฑํ ํ ๋์ค์ ์ ์ฅํ ๋ ์ ์ฉํฉ๋๋ค.
3.2. ๐ ์ฝ๊ธฐ (Read / Retrieve)
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํฉ๋๋ค. ์ ์ฒด ๋ชฉ๋ก์ ๋ณด๊ฑฐ๋, ํน์ ์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ๋ง ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค.
์ ์ฒด ๋ฐ์ดํฐ ์กฐํ:
Todo.objects.all()ํน์ ์กฐ๊ฑด ๋ฐ์ดํฐ ์กฐํ:
Todo.objects.filter(completed=False)ํ๋์ ๋ฐ์ดํฐ ์กฐํ:
Todo.objects.get(id=1)(๊ฒฐ๊ณผ๊ฐ ์๊ฑฐ๋ 2๊ฐ ์ด์์ด๋ฉด ์ค๋ฅ ๋ฐ์)
# crudapp/views.py - ์ผ๋ถ
def list_todos(request):
# 2. ๋ชจ๋ Todo ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ถ๋ฌ์ต๋๋ค.
todos = Todo.objects.all()
# ์ด ๋ฐ์ดํฐ๋ฅผ ํ
ํ๋ฆฟ์ ์ ๋ฌํ์ฌ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค๋๋ค.
return render(request, 'todo/list_todos.html', {'todos': todos})
3.3. ✏️ ์์ (Update)
๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ ํ๋ ๊ฐ์ ๋ณ๊ฒฝํ๊ณ ์ ์ฅํฉ๋๋ค.
# crudapp/views.py - ์ผ๋ถ
def update_todo(request, todo_id):
# 3. id๋ฅผ ์ด์ฉํด ์์ ํ Todo ๊ฐ์ฒด๋ฅผ ํ๋ ๋ถ๋ฌ์ต๋๋ค.
todo_item = Todo.objects.get(id=todo_id)
if request.method == 'POST':
new_title = request.POST.get('title')
# ๋ถ๋ฌ์จ ๊ฐ์ฒด์ ํ๋ ๊ฐ์ ์์ ํฉ๋๋ค.
todo_item.title = new_title
# ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํฉ๋๋ค. (์ ์ฅํ ๋ Update ์ฟผ๋ฆฌ๊ฐ ์คํ๋จ)
todo_item.save()
return redirect('list_url')
# ... (ํ
ํ๋ฆฟ ๋ ๋๋ง ์ฝ๋)
3.4. ❌ ์ญ์ (Delete)
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํน์ ๊ฐ์ฒด๋ฅผ ์์ ํ ์ ๊ฑฐํฉ๋๋ค.
# crudapp/views.py - ์ผ๋ถ
def delete_todo(request, todo_id):
# 4. id๋ฅผ ์ด์ฉํด ์ญ์ ํ Todo ๊ฐ์ฒด๋ฅผ ํ๋ ๋ถ๋ฌ์ต๋๋ค.
todo_item = Todo.objects.get(id=todo_id)
if request.method == 'POST':
# delete() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๊ฐ์ฒด๋ฅผ DB์์ ์ญ์ ํฉ๋๋ค.
todo_item.delete()
return redirect('list_url')
# ... (ํ
ํ๋ฆฟ ๋ ๋๋ง ์ฝ๋)
4. ๐ URL ๋ฐ ํ ํ๋ฆฟ ์ฐ๊ฒฐ
์์์ ์์ฑํ View ํจ์๋ค์ด ์น์์ ์ ๊ทผ ๊ฐ๋ฅํ๋ ค๋ฉด urls.py์ ๊ฒฝ๋ก๋ฅผ ์ฐ๊ฒฐํด ์ฃผ์ด์ผ ํฉ๋๋ค. ๋ํ, ์ฌ์ฉ์์๊ฒ ์
๋ ฅ/์ถ๋ ฅ ํ๋ฉด์ ์ ๊ณตํ๊ธฐ ์ํด ๊ฐ View์ ํด๋นํ๋ HTML ํ
ํ๋ฆฟ์ ์์ฑํด์ผ ํฉ๋๋ค.
| CRUD ์์ | View ํจ์ | URL ํจํด (์์) | HTTP ๋ฉ์๋ |
| Create | create_todo | /todo/new/ | GET (ํผ ํ์), POST (์์ฑ) |
| Read (List) | list_todos | /todo/ | GET |
| Update | update_todo | /todo/<int:todo_id>/edit/ | GET, POST |
| Delete | delete_todo | /todo/<int:todo_id>/delete/ | POST |
์ด์ฒ๋ผ Django์ MVT (Model-View-Template) ํจํด์ ํ์ฉํ์ฌ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ์ ์ํ๊ณ , View์์ CRUD ๋ก์ง์ ์ฒ๋ฆฌํ๋ฉฐ, Template์์ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ ๋ฐฉ์์ผ๋ก ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฑํ ์ ์์ต๋๋ค.
CRUD๋ ๋ชจ๋ Django ํ๋ก์ ํธ์ ๊ธฐ์ด ์ฒด๋ ฅ๊ณผ ๊ฐ์ต๋๋ค. ์ด ๋ค ๊ฐ์ง ๋์์ ์๋ฌํ๋ฉด ์ด๋ค ๋ณต์กํ ์น ์๋น์ค๋ผ๋ ๋ง๋ค ์ ์๋ ๊ธฐ๋ฐ์ ๋ค์ง๊ฒ ๋ฉ๋๋ค!
์ด ์์์ Django CRUD ์ ํ๋ฆฌ์ผ์ด์
์ Forms์ Models๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํ๋ ๊ณผ์ ์ ๋จ๊ณ๋ณ๋ก ์๋ดํด ์ค๋๋ค.

๋๊ธ
๋๊ธ ์ฐ๊ธฐ