Django ORM
1. ORM์ด๋?
ํญ๋ชฉ | ์ค๋ช
|
ORM (Object Relational Mapping) | DB ํ
์ด๋ธ |
Django ORM | SQL์ ์ง์ ์ฐ์ง ์๊ณ Python ๋ฌธ๋ฒ์ผ๋ก DB ์กฐ์ |
์ฅ์ | DB ๋
๋ฆฝ์ฑ, ์์ฐ์ฑ ํฅ์, ๋ณด์ ๊ฐํ (SQL Injection ๋ฐฉ์ง) |
2. ๋ชจ๋ธ ์ ์
# models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Python
๋ณต์ฌ
3. ๋ง์ด๊ทธ๋ ์ด์
(DB ๋ฐ์)
python manage.py makemigrations
python manage.py migrate
Shell
๋ณต์ฌ
4. ๊ธฐ๋ณธ CRUD ์ค์ต
Create
post = Post.objects.create(title='์ฒซ ๊ธ', content='์ฅ๊ณ ORM ์์!')
Python
๋ณต์ฌ
Read
Post.objects.all() # ์ ์ฒด ์กฐํ
Post.objects.get(id=1) # ๋จ์ผ ์กฐํ
Post.objects.filter(title='์ฒซ ๊ธ') # ์กฐ๊ฑด ์กฐํ
Python
๋ณต์ฌ
Update
post = Post.objects.get(id=1)
post.title = '์์ ๋ ์ ๋ชฉ'
post.save()
Python
๋ณต์ฌ
Delete
post = Post.objects.get(id=1)
post.delete()
Python
๋ณต์ฌ
5. Admin ์ฐ๋
# admin.py
from .models import Post
admin.site.register(Post)
Python
๋ณต์ฌ
๊ด๋ฆฌ์ ๊ณ์ ์์ฑ
python manage.py createsuperuser
Python
๋ณต์ฌ
๊ณ์ | ๊ฐ |
Username | admin |
Password | 123456 |
6. ๊ด๊ณํ ๋ชจ๋ธ ์ ์
1:N ๊ด๊ณ (์: ๊ธ-๋๊ธ)
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
Python
๋ณต์ฌ
# ๋๊ธ ์ถ๊ฐ
post = Post.objects.get(id=1)
post.comment_set.create(content="๋๊ธ์
๋๋ค")
Python
๋ณต์ฌ
7. ๊ณ ๊ธ ์ฟผ๋ฆฌ
filter() ๋ฉ์๋ ์ต์
์ต์
| ์ค๋ช
| ์์ |
exact | ์ ํํ ์ผ์น | filter(title__exact="์ ๋ชฉ") |
contains | ํฌํจ | filter(title__contains="์ฅ๊ณ ") |
startswith | ์์ ๋ฌธ์์ด | filter(title__startswith="Django") |
endswith | ๋ ๋ฌธ์์ด | filter(title__endswith="์๋ฃ") |
gt/gte | ์ด๊ณผ/์ด์ | filter(id__gte=5) |
lt/lte | ๋ฏธ๋ง/์ดํ | filter(id__lte=10) |
exclude() ๋ฉ์๋
filter()์ ๋ฐ๋ ๋์์ ์ํํ๋ฉฐ, ์กฐ๊ฑด์ ํด๋นํ์ง ์๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํฉ๋๋ค.
order_by() ๋ฉ์๋
โข
ํ๋๋ช
: ์ค๋ฆ์ฐจ์ ์ ๋ ฌ (์: order_by('title'))
โข
-ํ๋๋ช
: ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ (์: order_by('-created_at'))
โข
์ฌ๋ฌ ํ๋: ์ฝค๋ง๋ก ๊ตฌ๋ถ (์: order_by('-created_at', 'title'))
count() ๋ฉ์๋
์ฟผ๋ฆฌ์
์ ์ ์ฒด ๋ฐ์ดํฐ ๊ฐ์๋ฅผ ๋ฐํํฉ๋๋ค. SQL์ COUNT(*) ๊ธฐ๋ฅ๊ณผ ๋์ผํฉ๋๋ค.
exists() ๋ฉ์๋
์ฟผ๋ฆฌ์
์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋์ง ์ฌ๋ถ๋ฅผ Boolean์ผ๋ก ๋ฐํํฉ๋๋ค. ๋ฐ์ดํฐ ์กด์ฌ ์ฌ๋ถ๋ง ํ์ธํ ๋ ํจ์จ์ ์
๋๋ค.
values() ๋ฉ์๋
โข
์ง์ ๋ ํ๋๋ง ๋์
๋๋ฆฌ ํํ๋ก ์กฐํ
โข
ํน์ ํ๋๋ง ํ์ํ ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์ค์ผ ์ ์์
# ์์
Post.objects.values('title', 'created_at') # title๊ณผ created_at ํ๋๋ง ์กฐํ
Python
๋ณต์ฌ
annotate() ๋ฉ์๋
์ง๊ณ๋ ๊ณ์ฐ๋ ํ๋๋ฅผ ์ฟผ๋ฆฌ์
์ ์ถ๊ฐํฉ๋๋ค. ์ฃผ๋ก ์ง๊ณ ํจ์์ ํจ๊ป ์ฌ์ฉ๋ฉ๋๋ค.
# ์์ฑ์๋ณ ๊ฒ์๊ธ ์ ๊ณ์ฐ
from django.db.models import Count
Post.objects.values('author').annotate(post_count=Count('id'))
# ์นดํ
๊ณ ๋ฆฌ๋ณ ํ๊ท ์กฐํ์ ๊ณ์ฐ
from django.db.models import Avg
Post.objects.values('category').annotate(avg_views=Avg('views'))
Python
๋ณต์ฌ
Count, Avg, Sum, Min, Max ๋ฑ์ ์ง๊ณ ํจ์ ์ฌ์ฉ ๊ฐ๋ฅ
โข
GROUP BY ์ฟผ๋ฆฌ์ ์ ์ฌํ ๊ธฐ๋ฅ ์ํ
โข
๋ณต์กํ ๋ฐ์ดํฐ ๋ถ์์ด๋ ํต๊ณ ์์
์ ํ์ฉ
values() ์ annotate() ๋ฅผ ๊ฐ์ด ์ฌ์ฉํ๋ฉด์
Count, Avg ๋ฑ์ ๊ทธ๋ฃนํจ์๋ฅผ ์ฌ์ฉํ๋ฉด GROUP BY ์ ์ด ์๋์ผ๋ก ์ ์ฉ๋ฉ๋๋ค.
์ฟผ๋ฆฌ | ์์ |
filter() | Post.objects.filter(title__contains="์ฅ๊ณ ") |
exclude() | Post.objects.exclude(title__contains="ํ
์คํธ") |
order_by() | Post.objects.order_by('-created_at') |
count() | Post.objects.count() |
exists() | Post.objects.filter(id=3).exists() |
values() | Post.objects.values('title') |
Post.objects.filter(title__contains="์ฅ๊ณ ")
Python
๋ณต์ฌ
post ํ
์ด๋ธ์ title ์ปฌ๋ผ์ โ์ฅ๊ณ โ ๊ฐ ํฌํจ๋๋ ๋ฐ์ดํฐ๋ง ์กฐํ
SELECT *
FROM post
WHERE title LIKE '%์ฅ๊ณ %';
SQL
๋ณต์ฌ
Post.objects.exclude(title__contains="ํ
์คํธ")
Python
๋ณต์ฌ
post ํ
์ด๋ธ์ title ์ปฌ๋ผ์ โํ
์คํธโ ๊ฐ ํฌํจ๋์ง ์์ ๋ฐ์ดํฐ๋ง ์กฐํ
SELECT *
FROM post
WHERE title NOT LIKE '%ํ
์คํธ%';
SQL
๋ณต์ฌ
Post.objects.order_by('-created_at')
Python
๋ณต์ฌ
created_at (๋ฑ๋ก์ผ์) ์ปฌ๋ผ์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ
SELECT *
FROM post
ORDER BY created_at DESC;
SQL
๋ณต์ฌ
order_by(โํ๋๋ช
') : ์ค๋ฆ์ฐจ์
order_by(โ-ํ๋๋ช
') : ๋ด๋ฆผ์ฐจ์
Post.objects.order_by('-created_at', 'title')
Python
๋ณต์ฌ
์ฒซ ๋ฒ์งธ ์ ๋ ฌ ๊ธฐ์ค : created_at (๋ฑ๋ก์ผ์) ์ปฌ๋ผ์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ
๋ ๋ฒ์งธ ์ ๋ ฌ ๊ธฐ์ค : title (์ ๋ชฉ) ์ปฌ๋ผ์ ๊ธฐ์ค์ผ๋ก ์ค๋ฆ์ฐจ์ ์ ๋ ฌ
SELECT *
FROM post
ORDER BY created_at DESC
title ASC
;
SQL
๋ณต์ฌ
order_by(โํ๋๋ช
') : ์ค๋ฆ์ฐจ์
order_by(โ-ํ๋๋ช
') : ๋ด๋ฆผ์ฐจ์
Post.objects.count()
Python
๋ณต์ฌ
post ํ
์ด๋ธ์ ์ ์ฒด ๋ฐ์ดํฐ ๊ฐ์๋ฅผ ์กฐํ
SELECT COUNT(*)
FROM post
;
SQL
๋ณต์ฌ
from django.db.models import Count
Post.objects.values('writer').annotate(post_count=Count('*'))
Python
๋ณต์ฌ
์์ฑ์(writer) ๋ณ๋ก ๋ฐ์ดํฐ ๊ฐ์๋ฅผ ์กฐํ
SELECT writer, COUNT(*) AS post_count
FROM post
GROUP BY writer
;
SQL
๋ณต์ฌ
Post.objects.filter(id=3).exists()
SQL
๋ณต์ฌ
id ๊ฐ 3 ์ธ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด True, ์์ผ๋ฉด False
SELECT 1
FROM post
WHERE id = 3
LIMIT 1
;
SQL
๋ณต์ฌ
Post.objects.values('title')
SQL
๋ณต์ฌ
์ ์ฒด ์กฐํํ ๋ฐ์ดํฐ ์ค, title ์ปฌ๋ผ๋ง ์ถ๋ ฅ
SELECT title
FROM post
;
SQL
๋ณต์ฌ
[
{'title': '์ฅ๊ณ ์
๋ฌธ'},
{'title': 'Python ๊ธฐ์ด'},
{'title': '๊ฒ์ํ ๋ง๋ค๊ธฐ'},
...
]
Python
๋ณต์ฌ
8. ์ค์ต ์์
์ค์ต๋ช
| ๋ชฉํ |
๋ชจ๋ธ ์ ์ ๋ฐ ๋ง์ด๊ทธ๋ ์ด์
| Post, Comment ๋ชจ๋ธ ์์ฑ ํ DB ๋ฐ์ |
CRUD ๊ตฌํ | Shell ๋๋ ๋ทฐ์์ ๊ฒ์๊ธ ์์ฑ/์กฐํ/์์ /์ญ์ |
๊ด๊ณ ๋ชจ๋ธ ์ค์ต | ForeignKey๋ฅผ ํ์ฉํ 1:N ๊ด๊ณ ์ฐ๊ฒฐ |
๊ณ ๊ธ ํํฐ๋ง | ์กฐ๊ฑด ๊ฒ์, ์ ๋ ฌ, ๊ฐ์ ์ธ๊ธฐ ์ค์ต |