پر کردن مودال با استفاده از اطلاعات فرم

نیاز بود که توی یک جدول اگر توی سلول یکی از ستونها کلیک کردیم یک مودال باز بشود. اما باید اطلاعاتی مربوط به آن ردیف به مودال پاس بدیم. متوجه شدم که این اطلاعات مربوط به ردیف مذکور را میتوان به عنوان یک پایامتر به سلول مربوطه اضافه کرد مثل:

توی خود مودال یک سری فیلد خالی تعریف میکنیم که بعدا با جاواساکریپ اطلاعات پارامترها رو به اون اضافه کنیم:

الان توی اسکریپت زیر از هر ردیف سلول مربوطه رو بر اساس اسم کلاس میگیریم. بعد از اون سلول پارامترم مربوطه که دیتا بهش وصل شده رو بر میداریم بعد همون مقدارها رو به مودال میدیم:

annotate و عدم اعمال Index

این 2 کد را در نظر بگیرید:

و

با تبدیل اولی به دومی زمان این query از 450 میلی ثانیه به 45 میلی ثانیه کاهش پیدا کرد. چرا؟

دلیل این بود که فیلدهای این مدل همگی Index بودند اما این ایندکسها اعمال نمی شدند چونکه annotate باعث میشود که کل جدول اسکن شود و عملا ایندکسها بی فایده باشند بنابراین حداقل st=0 را به قبل از annotate انتقال دادیم و این باعث شد برای annotate که اتفاقا از WHERE استفاده میکند از ایندکس استفاده شود.

مقایسه دو تکه کد

تفاوت دو کد زیر چیست و کدام بهتر است؟

و

در کد اول اگر thumbnail توسط کاربر انتخاب نشود یک فایل از مسیر mag آپلود میشود. و هنگام پاک شدن آبجکت مربوطه، اگر این آبجکت دارای این فایل پیشفرض بود پاک نشود که البته در این کد مربوطه خود به خود پاک می شود. پس یک باگ وجود دارد. گذشته از این باگ اگر 1000 بار کاربر بدون thumbnail فایل آپلود کند 1000 فایل تکراری ذخیره میشود.

در ضمن اگر فایل بهر دلیلی پاک شود یا نام آن تغییر کند سیستم دچار مشکل میشود.

در کد دوم اما اگر کاربر فایلی انتخاب نکند هیچ فایل پیش فرضی آپلود نمیشود بنابراین فایل تکراری دیده نمی شود و فضا هدر نمی روند.

از طرفی یک فایل static پاک نشده و هرکجا یک سند thumbnail نداشته باشد با متد get_thumbnail_url این فایل نشان داده میشود و دیگر سیستم دچار باگهای ناخواسته نمی شود.

تغییر queryset توی فرم جنگو

توی یک فرم میخوایم فیلدی که لیستی را به کاربر نشان میدهد را تغییری بدیم که همه مواردی که توی اون فیلد توی دیتابیس نیست را نشان ندهیم.

صحت سنجی فرمت فایل توی فرم جنگو

چطور توی یک فرم اگر یک فایل آپلود شده از یک فرمت خاص نبود ارور برگردونیم

تبدیل n+1 عدد query به 3 query

این یک مثال واقعی از بهبود یک پروژه است. query اولیه به شکل زیر بود:

با ابزار django debug toolbar تعداد query های این تکه کد را مرور کردم و جاهایی که به سرور query زده میشود به این شکل است:

  1. در خط Branch.objects.get(name__iexact=”bss”).office_set.all() یک query به دیتابیس زده میشود.

2. در خط for el in bss_branch: یک query به دیتابیس زده می شود.

3. در خط for svc in el.services.all(): یک query به دیتابیس زده میشود. یعنی اگر در bss_branch تعداد N المان وجود داشته باشد به ازای هر کدام یک query در این قسمت زده خواهد شد.

یعنی برای هر el که تعداد آن به اندازه bss_branch هست یک query جدید داریم

بنا براین در کد بالا یک query زده شده و branch ها استخراج شده (در قسمت 1) که ترجمه آن:

در قسمت دوم یک query زده شده و office های آن branch استخراج شده:

در قسمت سوم به ازای هر کدام از office ها یک query زده شده و service های آن استخراج شده به عنوان مثال یکیش رو آوردم:

پس در مجموع N+1 درخواست دیتابیس query زدن شد.

حالا اینو بهینه میکنیم به کد زیر:

در این نمونه کد query های زیر را داریم:

  1. در خط bss_branch = Branch.objects.get(name__iexact=”bss”).office_set.prefetch_related(‘services’) یک query به دیتابیس داریم.
  2. در خط for el in bss_branch: یک query زده شده و office های branch را استخراج کرده.
  3. دوباره در همان خط یک query زده شده و service های تمامی office ها یک جا استخراج شده در این قسمت دیگر N بار query زده نشده

query قسمت 1

query قسمت 2

query قسمت 3

همانطور که توی کد بالا میبینید توی خط آخر تمامی query ها ادغام شده اند

بنابراین N+1 دستور query به 3 query تبدیل شد

مشکل ثبت مجدد فرم با رفرش

. توی کد زیر بعد از ثبت کردن فرم اگر صفحه را رفرش کنیم همان فرم دوباره ثبت میشود.

مشکل در فروم جنگو این جوری توضیح داده شده است:

یعنی بعد از POST موفق باید فرم را redirect کنیم که با این کار صفحه جدید با GET فراخوانی میشود در نتیجه اگر رفرش کنیم باز هم در خواست GET ارسال میگردد. یعنی کد را به شکل زیر تغییر میدهیم.

serializer توی Django Rest Framework با دیتای ورودی چیکار میکنه؟

بهترین روش یادگیری یه فریم ورک خوندن کد خود فریم ورک و داکیومنت توی خود کد هست. برای serializer توی جنگو یک کامنت هست توی rest_framework/serializer.py که:

خیلی خوب توضیح میده که اگر به serializer پارامتر data رو پاس داده باشیم تابع is_valid قابل استفاده است. و initial_data هم در دسترس هست که همون دیتایی هست که به API پاس داده شده. بعد از is_valid این داده ورودی به valid شده تبدیل میشه که میتونیم توی validated_data ببینیم. مثلا اگر Id به object مربوطه تبدیل میشه. و errors و data هم در دسترس خواهد بود. data درواقع اون رکورد جدیدی هست که ایجاد شده است.

مثال زیر رو ببینید:

میبینید که بعد serializer.is_valid() مقادیر مربوطه رو پرینت کردم.

مثال خروجی هم در ادامه میبینید:

بازنویسی serializer توی Django Rest Framework

توی serializer های DRF گاهی لازمه وقتی متد list() اون صدا زده میشه باید قبلش دیتایی که ازش گرفته میشه تغییری بدیم برای این کار از متد to_representaion استفاده میکنیم.

دپلوی React و Django در Docker

برای دپلوی کردن یک پروژه Django و React در داکر با کانفیگ زیر کار میکنیم:

فایل بالا compose است و فایل backend/shiftsupervisor/Dockerfile

و فایل frontend/shiftfront/Dockerfile

و فایل nginx/nginx.conf

در ضمن تنظیمات مهم برای settings.py

فایل axiosConfig.jsx

و فایل vite.config.js