>  기사  >  백엔드 개발  >  Django ORM 이해하기

Django ORM 이해하기

Mary-Kate Olsen
Mary-Kate Olsen원래의
2024-10-08 20:11:02470검색

Understanding Django ORM

ORM이란 무엇입니까?

객체 관계형 매핑(ORM)은 SQL 쿼리를 작성하지 않고도 Python 코드를 사용하여 데이터베이스와 상호 작용할 수 있게 해주는 Django의 기능입니다. ORM은 내부적으로 CRUD 작업을 SQL로 변환하여 데이터베이스 개체를 쉽게 생성, 검색, 업데이트 및 삭제할 수 있도록 합니다.

ORM 작업

Django에서 모델 클래스는 데이터베이스 테이블을 나타내고 해당 클래스의 인스턴스는 테이블의 레코드를 나타냅니다.

모든 모델에는 객체라고 하는 관리자가 하나 이상 있습니다. 이 관리자를 통해 데이터베이스에서 레코드를 검색하여 QuerySet을 생성할 수 있습니다.

QuerySet은 게으르다. 즉, 명시적으로 요청할 때까지 결과를 가져오지 않습니다.

일반 QuerySet 메소드
filter(): 특정 기준에 맞는 레코드를 검색합니다.
all(): 모든 기록을 검색합니다.
order_by(): 특정 필드를 기준으로 레코드를 주문합니다.
Unique(): 고유한 레코드를 반환합니다.
annotate(): 각 레코드에 집계 값을 추가합니다.
집계(): 쿼리셋에서 값을 계산합니다.
defer(): 모델의 일부 필드만 로드하고 다른 필드는 연기합니다.

고급 ORM 기능

Q 및 F 개체를 사용하면 복잡한 쿼리와 효율적인 데이터베이스 수준 작업이 가능합니다. OR 조건이 포함된 쿼리에는 'Q'를 사용할 수 있고, 'F'를 사용하면 쿼리에서 모델 필드를 직접 참조할 수 있습니다.

from django.db.models import Q, F

# Using Q to filter published posts or created after a specific date
posts = Post.objects.filter(Q(status='published') | Q(created_at__gte='2024-01-01'))

# Using F to compare fields within a model (e.g., for a discount calculation)
class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    discounted_price = models.DecimalField(max_digits=10, decimal_places=2)

# Retrieve products where discounted price is less than price
discounted_products = Product.objects.filter(discounted_price__lt=F('price'))

쿼리 표현식(모델 필드 참조) 및 데이터베이스 함수(SQL과 유사한 함수 적용) 모두 처리를 위해 데이터를 Python으로 가져오는 대신 데이터베이스 수준에서 작업을 수행할 수 있게 해줍니다. . 이는 쿼리를 최적화하고 데이터베이스 부하를 줄이는 데 도움이 됩니다.

from django.db.models import Count, Max

# Count the number of posts for each status
status_count = Post.objects.values('status').annotate(count=Count('id'))

# Get the latest created post
latest_post = Post.objects.aggregate(latest=Max('created_at'))

사용자 정의 관리자 추가 관리자 메소드를 추가하거나 관리자가 처음에 반환하는 QuerySet을 수정할 수 있습니다.

class PublishedManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(status='published')

class Post(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    status = models.CharField(max_length=50)
    created_at = models.DateTimeField(auto_now_add=True)

    objects = models.Manager()  # Default manager
    published = PublishedManager()  # Custom manager for published posts

# Use the custom manager to get published posts
published_posts = Post.published.all()

ContentType은 직접적인 외래 키를 사용하여 모델을 지정하지 않고 모델 간의 일반적인 관계를 생성하는 데 유용한 모델입니다. 일반적인 사용 사례에는 다양한 유형의 모델에 첨부해야 하는 댓글이나 태그가 포함됩니다.

from django.contrib.contenttypes.models import ContentType

# Example model for comments
class Comment(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    text = models.TextField()

# Creating a comment for a Post instance
post = Post.objects.get(id=1)
comment = Comment.objects.create(
    content_type=ContentType.objects.get_for_model(Post),
    object_id=post.id,
    text='Great post!'
)

트랜잭션은 데이터베이스 작업을 단일 단위로 묶어 데이터 일관성을 보장합니다. @transaction.atomic 데코레이터 또는 transaction.atomic() 컨텍스트 관리자를 사용하여 트랜잭션 블록에 코드를 래핑할 수 있습니다.

from django.db import transaction

# Using a transaction block
with transaction.atomic():
    post = Post.objects.create(title='New Post', content='Content here...', status='published')
    # Any other database operations will be part of this transaction

Django에서는 유연성이 필요한 복잡한 쿼리에 대해 원시 SQL 쿼리를 실행할 수 있습니다. 하지만 주의해서 사용해야 합니다.

from django.db import connection

def get_published_posts():
    with connection.cursor() as cursor:
        cursor.execute("SELECT * FROM blog_post WHERE status = %s", ['published'])
        rows = cursor.fetchall()
    return rows

결론

Django의 ORM은 모델, 관리자 및 쿼리 작업을 위한 고급 API를 제공하여 데이터베이스 상호 작용을 단순화합니다. 이러한 기능을 이해하고 활용하면 생산성과 애플리케이션 성능이 크게 향상될 수 있습니다.

위 내용은 Django ORM 이해하기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.