در Django ORM، گاهی اوقات نیاز به انجام عملیاتهای پیچیدهتر روی دادهها داریم که به ما این امکان را میدهد که دقیقتر و بهینهتر با دادهها کار کنیم. این عملیاتها شامل فیلترهای پیچیده با استفاده از Q()
، ترکیب فیلترها، استفاده از توابع تجمعی (aggregate()
) و محاسبات روی دادهها با annotate()
، و همچنین استفاده از قابلیتهای دیگر ORM است.
در مواردی که نیاز به فیلترهای پیچیده داریم، از Q()
استفاده میکنیم. این ابزار به ما این امکان را میدهد که شرایط مختلف را با استفاده از AND و OR ترکیب کنیم.
from django.db.models import Q
# بازیابی پستهایی که نویسنده آنها user1 باشد یا عنوان آنها حاوی "Python" باشد
posts = Post.objects.filter(Q(author=user1) | Q(title__icontains='Python'))
در این مثال، با استفاده از Q()
دو شرط را با OR ترکیب کردهایم. یعنی همه پستهایی که نویسنده آنها برابر با user1
است یا عنوان آنها شامل کلمه "Python" میشود را بازیابی خواهیم کرد.
# بازیابی پستهایی که هم نویسنده آنها user1 باشد و هم عنوان آنها حاوی "Django" باشد
posts = Post.objects.filter(Q(author=user1) & Q(title__icontains='Django'))
در اینجا، دو شرط با استفاده از AND ترکیب شدهاند و پستهایی که هر دو شرط را برآورده میکنند، باز میگردند.
# بازیابی پستهایی که نویسنده آنها user1 نباشد
posts = Post.objects.filter(~Q(author=user1))
در این مثال، با استفاده از ~
فیلتر کردهایم تا همه پستهایی که نویسنده آنها user1
نباشد را پیدا کنیم.
با استفاده از متد aggregate()
، میتوانیم عملیاتهای تجمعی مانند محاسبه مجموع، میانگین، حداقل و حداکثر روی دادهها انجام دهیم.
from django.db.models import Sum, Avg
# محاسبه مجموع و میانگین قیمتها
result = Product.objects.aggregate(Sum('price'), Avg('price'))
در این مثال، aggregate()
دو عملیات تجمعی انجام میدهد: محاسبه مجموع و میانگین فیلد price
برای تمامی محصولات.
from django.db.models import Max, Min
# محاسبه حداکثر و حداقل قیمتها
result = Product.objects.aggregate(Max('price'), Min('price'))
در این مثال، با استفاده از aggregate()
حداکثر و حداقل قیمتهای محصولات را محاسبه کردهایم.
annotate()
به ما این امکان را میدهد که مقادیر محاسبهشده را به هر رکورد یا شیء در QuerySet اضافه کنیم.
from django.db.models import Count
# شمارش تعداد نظرات برای هر پست
posts = Post.objects.annotate(num_comments=Count('comments'))
در این مثال، با استفاده از annotate()
تعداد نظرات هر پست به عنوان یک فیلد جدید num_comments
به هر پست افزوده میشود.
from django.db.models import Avg
# محاسبه میانگین قیمتها برای هر دستهبندی
categories = Category.objects.annotate(avg_price=Avg('products__price'))
در این مثال، با استفاده از annotate()
میانگین قیمتها برای هر دستهبندی محاسبه میشود.
در Django، برای بهینهسازی عملکرد و جلوگیری از ایجاد تعداد زیاد کوئریهای پایگاه داده، از متدهای select_related()
و prefetch_related()
استفاده میشود. این متدها به شما این امکان را میدهند که دادههای مرتبط را با یک کوئری و به صورت مؤثر بارگذاری کنید.
# بارگذاری اطلاعات نویسنده با استفاده از join
posts = Post.objects.select_related('author').all()
در این مثال، اطلاعات نویسنده برای هر پست با استفاده از select_related()
بارگذاری میشود و فقط یک کوئری برای دریافت پستها و نویسندگان آنها انجام میشود.
# بارگذاری اطلاعات محصولات مرتبط با هر دستهبندی
categories = Category.objects.prefetch_related('products').all()
در این مثال، اطلاعات محصولات مرتبط با هر دستهبندی به صورت جداگانه بارگذاری میشود و سپس به دادههای مربوطه افزوده میشود.
گاهی اوقات ممکن است بخواهید بررسی کنید که آیا یک QuerySet حداقل یک نتیجه دارد یا خیر. متد exists()
این کار را به صورت بهینه انجام میدهد.
# بررسی وجود پستهایی که حاوی کلمه "Django" در عنوان هستند
exists = Post.objects.filter(title__icontains='Django').exists()
در این مثال، exists()
بررسی میکند که آیا هیچ پستی با عنوان حاوی "Django" وجود دارد یا خیر.
در این فصل، بررسی کردیم که چگونه با استفاده از ابزارهای پیچیده Django ORM مانند Q()
, aggregate()
, annotate()
, و روشهای بهینهسازی مانند select_related()
و prefetch_related()
, میتوانیم عملیاتهای پیچیده و پیشرفتهتری را روی دادهها انجام دهیم. این ابزارها به شما این امکان را میدهند که به صورت بهینه و مؤثرتر با دادههای خود کار کنید.