Search
Duplicate

Django ORM

Django ORM

1. ORM์ด๋ž€?

ํ•ญ๋ชฉ
์„ค๋ช…
ORM (Object Relational Mapping)
DB ํ…Œ์ด๋ธ” Python ๊ฐ์ฒด ๋งคํ•‘
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 ๊ด€๊ณ„ ์—ฐ๊ฒฐ
๊ณ ๊ธ‰ ํ•„ํ„ฐ๋ง
์กฐ๊ฑด ๊ฒ€์ƒ‰, ์ •๋ ฌ, ๊ฐœ์ˆ˜ ์„ธ๊ธฐ ์‹ค์Šต