Skip to content

Latest commit

 

History

History
135 lines (83 loc) · 7.48 KB

5-Complex-and-Advanced-Operations-with-QuerySets-in-Django-ORM.md

File metadata and controls

135 lines (83 loc) · 7.48 KB

5. عملیات‌های پیچیده و پیشرفته با QuerySet ها در Django ORM

در Django ORM، گاهی اوقات نیاز به انجام عملیات‌های پیچیده‌تر روی داده‌ها داریم که به ما این امکان را می‌دهد که دقیق‌تر و بهینه‌تر با داده‌ها کار کنیم. این عملیات‌ها شامل فیلترهای پیچیده با استفاده از Q()، ترکیب فیلترها، استفاده از توابع تجمعی (aggregate()) و محاسبات روی داده‌ها با annotate()، و همچنین استفاده از قابلیت‌های دیگر ORM است.

5.1. استفاده از Q() برای فیلترهای پیچیده

در مواردی که نیاز به فیلترهای پیچیده داریم، از Q() استفاده می‌کنیم. این ابزار به ما این امکان را می‌دهد که شرایط مختلف را با استفاده از AND و OR ترکیب کنیم.

5.1.1. فیلتر با استفاده از Q() و OR

from django.db.models import Q

# بازیابی پست‌هایی که نویسنده آن‌ها user1 باشد یا عنوان آن‌ها حاوی "Python" باشد
posts = Post.objects.filter(Q(author=user1) | Q(title__icontains='Python'))

در این مثال، با استفاده از Q() دو شرط را با OR ترکیب کرده‌ایم. یعنی همه پست‌هایی که نویسنده آن‌ها برابر با user1 است یا عنوان آن‌ها شامل کلمه "Python" می‌شود را بازیابی خواهیم کرد.

5.1.2. فیلتر با استفاده از Q() و AND

# بازیابی پست‌هایی که هم نویسنده آن‌ها user1 باشد و هم عنوان آن‌ها حاوی "Django" باشد
posts = Post.objects.filter(Q(author=user1) & Q(title__icontains='Django'))

در اینجا، دو شرط با استفاده از AND ترکیب شده‌اند و پست‌هایی که هر دو شرط را برآورده می‌کنند، باز می‌گردند.

5.1.3. استفاده از Q() برای شرایط NOT یا NEGATIVE

# بازیابی پست‌هایی که نویسنده آن‌ها user1 نباشد
posts = Post.objects.filter(~Q(author=user1))

در این مثال، با استفاده از ~ فیلتر کرده‌ایم تا همه پست‌هایی که نویسنده آن‌ها user1 نباشد را پیدا کنیم.


5.2. استفاده از aggregate() برای عملیات تجمعی

با استفاده از متد aggregate()، می‌توانیم عملیات‌های تجمعی مانند محاسبه مجموع، میانگین، حداقل و حداکثر روی داده‌ها انجام دهیم.

5.2.1. محاسبه مجموع و میانگین

from django.db.models import Sum, Avg

# محاسبه مجموع و میانگین قیمت‌ها
result = Product.objects.aggregate(Sum('price'), Avg('price'))

در این مثال، aggregate() دو عملیات تجمعی انجام می‌دهد: محاسبه مجموع و میانگین فیلد price برای تمامی محصولات.

5.2.2. محاسبه حداکثر و حداقل

from django.db.models import Max, Min

# محاسبه حداکثر و حداقل قیمت‌ها
result = Product.objects.aggregate(Max('price'), Min('price'))

در این مثال، با استفاده از aggregate() حداکثر و حداقل قیمت‌های محصولات را محاسبه کرده‌ایم.


5.3. استفاده از annotate() برای افزودن مقادیر محاسبه‌شده

annotate() به ما این امکان را می‌دهد که مقادیر محاسبه‌شده را به هر رکورد یا شیء در QuerySet اضافه کنیم.

5.3.1. شمارش تعداد نظرات برای هر پست

from django.db.models import Count

# شمارش تعداد نظرات برای هر پست
posts = Post.objects.annotate(num_comments=Count('comments'))

در این مثال، با استفاده از annotate() تعداد نظرات هر پست به عنوان یک فیلد جدید num_comments به هر پست افزوده می‌شود.

5.3.2. محاسبه میانگین قیمت‌ها برای هر دسته‌بندی

from django.db.models import Avg

# محاسبه میانگین قیمت‌ها برای هر دسته‌بندی
categories = Category.objects.annotate(avg_price=Avg('products__price'))

در این مثال، با استفاده از annotate() میانگین قیمت‌ها برای هر دسته‌بندی محاسبه می‌شود.


5.4. استفاده از select_related() و prefetch_related() برای بهینه‌سازی Query ها

در Django، برای بهینه‌سازی عملکرد و جلوگیری از ایجاد تعداد زیاد کوئری‌های پایگاه داده، از متدهای select_related() و prefetch_related() استفاده می‌شود. این متدها به شما این امکان را می‌دهند که داده‌های مرتبط را با یک کوئری و به صورت مؤثر بارگذاری کنید.

5.4.1. استفاده از select_related() برای روابط یک به یک یا یک به چند

# بارگذاری اطلاعات نویسنده با استفاده از join
posts = Post.objects.select_related('author').all()

در این مثال، اطلاعات نویسنده برای هر پست با استفاده از select_related() بارگذاری می‌شود و فقط یک کوئری برای دریافت پست‌ها و نویسندگان آن‌ها انجام می‌شود.

5.4.2. استفاده از prefetch_related() برای روابط چند به چند

# بارگذاری اطلاعات محصولات مرتبط با هر دسته‌بندی
categories = Category.objects.prefetch_related('products').all()

در این مثال، اطلاعات محصولات مرتبط با هر دسته‌بندی به صورت جداگانه بارگذاری می‌شود و سپس به داده‌های مربوطه افزوده می‌شود.


5.5. استفاده از exists() برای بررسی وجود داده‌ها

گاهی اوقات ممکن است بخواهید بررسی کنید که آیا یک QuerySet حداقل یک نتیجه دارد یا خیر. متد exists() این کار را به صورت بهینه انجام می‌دهد.

# بررسی وجود پست‌هایی که حاوی کلمه "Django" در عنوان هستند
exists = Post.objects.filter(title__icontains='Django').exists()

در این مثال، exists() بررسی می‌کند که آیا هیچ پستی با عنوان حاوی "Django" وجود دارد یا خیر.


5.5. نتیجه‌گیری

در این فصل، بررسی کردیم که چگونه با استفاده از ابزارهای پیچیده Django ORM مانند Q(), aggregate(), annotate(), و روش‌های بهینه‌سازی مانند select_related() و prefetch_related(), می‌توانیم عملیات‌های پیچیده و پیشرفته‌تری را روی داده‌ها انجام دهیم. این ابزارها به شما این امکان را می‌دهند که به صورت بهینه و مؤثرتر با داده‌های خود کار کنید.