ORM(Object-Relational Mapping) ์ด๋? ๐บ๏ธ
1. ORM ์ ์
Django ORM(Object-Relational Mapping)์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ Python ๊ฐ์ฒด ๊ฐ์ ๋งคํ์ ๋์์ฃผ๋ Django์ ๊ธฐ๋ฅ์ด๋ค
- ์ฅ์ : SQL์ ์ง์ ์์ฑํ์ง ์๊ณ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ํํ ์ ์์
- ๋ชฉ์ : ์์ฐ์ฑ ํฅ์ ๋ฐ ์ฝ๋์ ๊ฐ๋ ์ฑ์ ์ ์งํ ์ ์์
2. Django ORM์ ์ฃผ์ ๊ตฌ์ฑ ์์
1) ๋ชจ๋ธ(Model)
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ ๊ตฌ์กฐ๋ฅผ ์ ์ํ๋ Python ํด๋์ค์ด๋ค
- ๋ชจ๋ธ์ ํ๋๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ด(Column)์ ๋์ํ๋ค
์์ :
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) # ์์ฑ ์๊ฐ
updated_at = models.DateTimeField(auto_now=True) # ์์ ์๊ฐ
def __str__(self):
return self.title
2) QuerySet
- Django ORM์ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฒ์๋ ๊ฐ์ฒด ์งํฉ์
- SQL ์ฟผ๋ฆฌ ๋์ ์ Python ๋ฌธ๋ฒ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์กฐํ, ํํฐ๋ง, ์ ๋ ฌ, ์ ๋ฐ์ดํธ๊ฐ ๊ฐ๋ฅํจ
์์ :
from myapp.models import Post
# ๋ชจ๋ Post ๊ฐ์ฒด ๊ฐ์ ธ์ค๊ธฐ
posts = Post.objects.all()
# ํน์ ์กฐ๊ฑด ํํฐ๋ง
filtered_posts = Post.objects.filter(title__contains="Django")
# ์ฒซ ๋ฒ์งธ ๊ฐ์ฒด ๊ฐ์ ธ์ค๊ธฐ
first_post = Post.objects.first()
3. ์ฃผ์ ORM ์์
1) ๋ฐ์ดํฐ ์์ฑ(Create)
post = Post(title="Hello Django", content="Django ORM is powerful!")
post.save() # ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ
Post.objects.create(title="Quick Create", content="Using ORM.")
2) ๋ฐ์ดํฐ ์ฝ๊ธฐ(Read)
# ๋ชจ๋ ๊ฐ์ฒด ๊ฐ์ ธ์ค๊ธฐ
Post.objects.all()
# ํน์ ์กฐ๊ฑด์ ๋ง๋ ๊ฐ์ฒด ๊ฐ์ ธ์ค๊ธฐ
Post.objects.filter(title="Hello Django")
# ๋จ์ผ ๊ฐ์ฒด ๊ฐ์ ธ์ค๊ธฐ (์กฐ๊ฑด ๋ถ์ถฉ์กฑ ์ ์์ธ ๋ฐ์)
Post.objects.get(id=1)
# ์ ๋ ฌ
Post.objects.order_by('-created_at') # ์ต์ ์
3) ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ(Update)
post = Post.objects.get(id=1)
post.title = "Updated Title"
post.save() # ๋ณ๊ฒฝ ์ฌํญ ์ ์ฅ
Post.objects.filter(id=1).update(title="Bulk Update Title")
4) ๋ฐ์ดํฐ ์ญ์ (Delete)
post = Post.objects.get(id=1)
post.delete() # ๊ฐ์ฒด ์ญ์
Post.objects.filter(title="Quick Create").delete()
4. ํ๋ ํ์
Django ํ๋ | ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ๋ | ์ค๋ช |
`CharField` | `VARCHAR` | ๋ฌธ์์ด (์ต๋ ๊ธธ์ด ์ง์ ํ์) |
`TextField` | `TEXT` | ๊ธด ๋ฌธ์์ด |
`IntegerField` | `INTEGER` | ์ ์ํ |
`BooleanField` | `BOOLEAN` | ์ฐธ/๊ฑฐ์ง |
`DateTimeField` | `DATETIME` | ๋ ์ง์ ์๊ฐ |
`ForeignKey` | `FOREIGN KEY` | ๋ค๋ฅธ ํ ์ด๋ธ๊ณผ์ ๊ด๊ณ ์ค์ |
`ManyToManyField` | `MANY-TO-MANY` | ๋ค๋๋ค ๊ด๊ณ |
`DecimalField` | `DECIMAL` | ๊ณ ์ ์์์ ์ซ์ |
5. ORM ํํฐ๋ง ์กฐ๊ฑด
1) ๊ธฐ๋ณธ ์กฐ๊ฑด
- `exact`: ์ ํํ ์ผ์น
- `contains`: ํน์ ๋ฌธ์์ด ํฌํจ
- `startswith`, `endswith`: ํน์ ๋ฌธ์์ด๋ก ์์/๋
Post.objects.filter(title__contains="Django")
2) ๋น๊ต ์ฐ์ฐ์
- `lt` (less than): ์๋ค
- `lte` (less than or equal to): ์๊ฑฐ๋ ๊ฐ๋ค
- `gt` (greater than): ํฌ๋ค
- `gte` (greater than or equal to): ํฌ๊ฑฐ๋ ๊ฐ๋ค
Post.objects.filter(created_at__gte="2025-01-01")
3) ๋ ผ๋ฆฌ ์ฐ์ฐ์
- `Q` ๊ฐ์ฒด: OR, AND ์กฐ๊ฑด ๊ฒฐํฉ
- `exclude()`: NOT ์กฐ๊ฑด
from django.db.models import Q
# OR ์กฐ๊ฑด
Post.objects.filter(Q(title__contains="Django") | Q(content__contains="ORM"))
# AND ์กฐ๊ฑด
Post.objects.filter(Q(title__startswith="Hello") & Q(content__contains="Django"))
# NOT ์กฐ๊ฑด
Post.objects.exclude(title="Old Post")
6. ๊ด๊ณํ ๋ฐ์ดํฐ ์์
1) ForeignKey
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField()
# ๊ด๊ณ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
post = Post.objects.get(id=1)
comments = post.comment_set.all()
2) ManyToManyField
class Tag(models.Model):
name = models.CharField(max_length=30)
class Post(models.Model):
title = models.CharField(max_length=100)
tags = models.ManyToManyField(Tag)
# Many-to-Many ๋ฐ์ดํฐ ์ถ๊ฐ
tag = Tag.objects.create(name="Python")
post = Post.objects.get(id=1)
post.tags.add(tag)
7. ์ฅ์ ๊ณผ ์ฃผ์์
์ฅ์
- ์์ฐ์ฑ: ๋ณต์กํ SQL ์์ฑ ์์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ๊ฐ๋ฅํ๋ค
- ์ ์ง๋ณด์: Python ์ฝ๋๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ๊ด๋ฆฌํจ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ๋ฆฝ์ฑ: ORM์ด ๋ค์ํ DB ๋ฐฑ์๋๋ฅผ ์ง์ํจ
์ฃผ์์
- ์ฑ๋ฅ ๋ฌธ์ : ๋ณต์กํ ์ฟผ๋ฆฌ์์ ์ฑ๋ฅ ์ ํ ๊ฐ๋ฅ (SQL ์ง์ ์์ฑ ํ์)
- N+1 ๋ฌธ์ : ์ฐ๊ด๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณต ์กฐํ ์ ๋ฐ์ํจ (`select_related`, `prefetch_related` ์ฌ์ฉ)
- ๋ณต์กํ ์ฟผ๋ฆฌ์ ํ๊ณ: ๊ณ ๊ธ SQL ๊ธฐ๋ฅ ์ฌ์ฉ ์ ํ๊ณ์
8. ๊ณ ๊ธ ๊ธฐ๋ฅ
- `select_related`: ForeignKey๋ก ์ฐ๊ฒฐ๋ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์ฟผ๋ฆฌ๋ก ๊ฐ์ ธ์ด
- `prefetch_related`: ManyToMany์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ฐ์ ธ์ด
- Raw SQL: ๋ณต์กํ ์ฟผ๋ฆฌ๋ ์ง์ ์์ฑ ๊ฐ๋ฅํจ
Post.objects.select_related('author').all()
Post.objects.prefetch_related('tags').all()
์ ๋ฆฌ ๐งน
- Django ORM์ SQL ์์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ฝ๊ฒ ์ํํ ์ ์๋๋ก ๋์์ค
- ๋ชจ๋ธ, QuerySet, ๊ด๊ณ ์ค์ ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๋ค
- ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด `select_related`, `prefetch_related`๋ฅผ ์ ๊ทน ํ์ฉํจ
- ๋ณต์กํ SQL ์์ ์ด ํ์ํ ๊ฒฝ์ฐ, Raw SQL๊ณผ ๋ณํํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค
'AI ๐ค > Django โ๏ธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[250115] REST ์ RESTful ์ ๋ํ ์ ๋ฐ์ ์ธ ๊ฐ๋ ์ ๋ฆฌ~ (1) | 2025.01.15 |
---|---|
[250114] Django์ ๋ค์ค App๊ณผ URL์ด๋? (0) | 2025.01.14 |
[250107] ํธ๋ ์ผ๋ง ์ฌ๋์(Trailing Slash) ๋? (0) | 2025.01.07 |
[250106] HTML ํผ(Form), ์ฟผ๋ฆฌ์คํธ๋ง(Query String), ๊ทธ๋ฆฌ๊ณ Get (0) | 2025.01.06 |
[250103] Django Template Language ๋? (1) | 2025.01.04 |