جنگولرن
آیا می دانستید که وقتی ImageField یا FileField توی جنگو دارید، و اون رکورد حذف میشه، فایل هاش حذف نمیشن درسته؟ قبول داری؟ تا جایی که من میدونم فایل ها حذف نمیشن یا مثلا عکس رو تغییر بدیم، عکس قبلی ع توی سرور میمونه در واقع media حذف نمیشه راه حل چیه؟ …
نظر دوستان در مورد این پست:
کانال django experience نوشته:
پست خیلی خوبی بود گفتم اینجا هم اشتراک بزارم
من همیشه از django clean up استفاده میکردم و django lifecycle رو اولین بار بود میشنیدم اینکه از سیگنال استفاده نمیکنه خیلی جالب بود برام
داخل پروژه های بزرگ معمولا یه تسک دوره ای مثل celery beat میزارن که پوشه ی media رو اسکن کنه و فایل هایی که بی صاحاب شدن رو حذف کنه چون همیشه هم حذف رکورد از طریق orm انجام نمیشه که سیگنال یا lifecycle بتونه واکنش نشون بده
آقای جبار زاده نوشته:
میشه کلاس storage رو override کرد و این قابلیت ها رو داخلش قرار داد
تمیز تر از سیگنال و امثالش هست
کانال django experience نوشته:
پست خیلی خوبی بود گفتم اینجا هم اشتراک بزارم
من همیشه از django clean up استفاده میکردم و django lifecycle رو اولین بار بود میشنیدم اینکه از سیگنال استفاده نمیکنه خیلی جالب بود برام
داخل پروژه های بزرگ معمولا یه تسک دوره ای مثل celery beat میزارن که پوشه ی media رو اسکن کنه و فایل هایی که بی صاحاب شدن رو حذف کنه چون همیشه هم حذف رکورد از طریق orm انجام نمیشه که سیگنال یا lifecycle بتونه واکنش نشون بده
آقای جبار زاده نوشته:
میشه کلاس storage رو override کرد و این قابلیت ها رو داخلش قرار داد
تمیز تر از سیگنال و امثالش هست
👍12
Media is too big
VIEW IN TELEGRAM
پشت صحنه دستور pip install django چیه؟
یا غوداااا اینو تقریبا 4 سال و نیم پیش ضبط کردم.
خودم تا آخرش دیدم، یادم نبود چی میشه.
✔️ کاربرد فایل های setup.py و setup.cfg چیه؟
✔️ دستور pip install چطور متوجه وابستگی یا همون dependency های پکیج ها میشه؟
✔️ چطور میتونیم django-admin رو عوض کنیم و به جای اون از milad-admin استفاده کنیم؟ 😂
✅ جواب همه سوال های بالا رو توی یه ویدئو ۱۲ دقیقه ای بهتون میگم.
لینک آپارات:
https://www.aparat.com/v/ofjc5
لینک یوتیوب:
https://youtu.be/DUP9YU7_6jo
یا غوداااا اینو تقریبا 4 سال و نیم پیش ضبط کردم.
خودم تا آخرش دیدم، یادم نبود چی میشه.
✔️ کاربرد فایل های setup.py و setup.cfg چیه؟
✔️ دستور pip install چطور متوجه وابستگی یا همون dependency های پکیج ها میشه؟
✔️ چطور میتونیم django-admin رو عوض کنیم و به جای اون از milad-admin استفاده کنیم؟ 😂
✅ جواب همه سوال های بالا رو توی یه ویدئو ۱۲ دقیقه ای بهتون میگم.
لینک آپارات:
https://www.aparat.com/v/ofjc5
لینک یوتیوب:
https://youtu.be/DUP9YU7_6jo
🔥13❤4👍3🆒1
Forwarded from سید فرندز / برنامه نویسی / هک و امنیت / تکنولوژی (Mohammad Khoshnava)
پست محسن باقری CTO شرکت irantic در لینکدین :
فروش ۲۸ هزار صندلی در کمتر از ۱۵ دقیقه!!!
یکی از نفسگیرترین لحظهها در صنعت تیکتینگ، شروع فروش یک ایونت بزرگ هستش.
روی صفحه همهچیز ساده به نظر میاد: یک دکمهی "خرید بلیت" و تمام.
ولی پشت صحنه چه اتفاقهایی باعث میشه فروشی در این مقیاس به درستی انجام بشه؟ هزاران درخواست در یک لحظه به سرورها هجوم میارن و هر ثانیهاش میتونه تعیینکننده باشه.
ما سالها در Irantic روی تیکتینگ سینما کار کردیم؛ جایی که بار روی سامانه بهصورت یکنواخت و تدریجی پخش میشه.
اما وقتی رسیدیم به کنسرت علیرضا قربانی در پارکینگ ورزشگاه آزادی، همهچیز فرق کرد.
استقبال عجیب کاربرها، محدود بودن صندلیها و رقابت شدید باعث شد تجربهای کاملاً متفاوت رو پشت سر بذاریم.
اینجا همهچیز به چند ثانیه بستگی داشت. باید اپلیکیشن رو برای خرید بیش از صد هزار کاربر همزمان مدیریت میکردیم و در عین حال جلوی Race Conditionهایی رو میگرفتیم که میتونستن کل خرید رو به هم بریزن.
برای رسیدن به این هدف، تغییرات مهمی در سیستم دادیم:
- درخواستها رو با لیستها و کلیدهای مختلف در Redis بازطراحی کردیم تا هر لیست مستقل مدیریت بشه.
-بهینهسازی حجم دادههای اپلیکیشن یکی از سختترین چالشها بود. ما باید حجم ریسپانس را طوری کاهش میدادیم که بدون از دست دادن اطلاعات حیاتی، به اندازهای کوچک بشه که معمولاً در یک سگمنت TCP منتقل بشه. وقتی داده در حجم پایین ارسال میشه، سرعت دریافت بالاتر، تأخیر کمتر و احتمال خطا نیز کمتر خواهد بود .البته در بعضی لحظات، حجم داده بیشتر از چند بایت میشد، ولی همون بهینهسازی برای چند ثانیهی طلایی فروش، تفاوت بزرگی ایجاد کرد.
- کش رو طوری تنظیم کردیم که هر لیست با سیاست خودش پاک بشه.
- یک مرحلهی میانی به رزرو اضافه کردیم تا متد اصلی سبکتر بمونه.
- در فرانتاند، مهمترین دغدغه نمایش درست و استفاده بهینه از ریسورس ها در دستگاهها بود. وقتی کاربر روی موبایل یا دسکتاپ وارد میشه، انتظار داره تجربهای روان و بینقص داشته باشه. این یعنی رندر شدن سریع صندلیها، الگوریتمهای دقیق برای جایگذاری صندلیها در حالتهای مختلف صفحه، و جلوگیری از افت کیفیت یا کندی. کوچکترین باگ در این بخش میتونست کل تجربه خرید رو خراب کنه
- در زیرساخت (DevOps)، پایداری و مانیتورینگ مهمترین بخش برای ما بود. آمادهسازی برای پیک ترافیک و مانیتورینگ لحظهای باعث شد حتی در اوج فشار، سامانه بدون مشکل کارش رو انجام بده.
- بخش مهم دیگه، انجام استرستستهای واقعی بود؛ جایی که با شبیهسازی بار سنگین روی سامانه، قبل از روز رویداد تمام نقاط ضعف احتمالی رو شناسایی و رفع کردیم. همین تستها باعث شد لحظهی اصلی، غافلگیر نشیم.
نتیجه؟
تمام ۲۸ هزار صندلی در کمتر از ۱۵ دقیقه سولد اوت شد، بدون اینکه تجربهی خرید کاربرها خدشهدار بشه.
✅ @SEYED_BAX
فروش ۲۸ هزار صندلی در کمتر از ۱۵ دقیقه!!!
یکی از نفسگیرترین لحظهها در صنعت تیکتینگ، شروع فروش یک ایونت بزرگ هستش.
روی صفحه همهچیز ساده به نظر میاد: یک دکمهی "خرید بلیت" و تمام.
ولی پشت صحنه چه اتفاقهایی باعث میشه فروشی در این مقیاس به درستی انجام بشه؟ هزاران درخواست در یک لحظه به سرورها هجوم میارن و هر ثانیهاش میتونه تعیینکننده باشه.
ما سالها در Irantic روی تیکتینگ سینما کار کردیم؛ جایی که بار روی سامانه بهصورت یکنواخت و تدریجی پخش میشه.
اما وقتی رسیدیم به کنسرت علیرضا قربانی در پارکینگ ورزشگاه آزادی، همهچیز فرق کرد.
استقبال عجیب کاربرها، محدود بودن صندلیها و رقابت شدید باعث شد تجربهای کاملاً متفاوت رو پشت سر بذاریم.
اینجا همهچیز به چند ثانیه بستگی داشت. باید اپلیکیشن رو برای خرید بیش از صد هزار کاربر همزمان مدیریت میکردیم و در عین حال جلوی Race Conditionهایی رو میگرفتیم که میتونستن کل خرید رو به هم بریزن.
برای رسیدن به این هدف، تغییرات مهمی در سیستم دادیم:
- درخواستها رو با لیستها و کلیدهای مختلف در Redis بازطراحی کردیم تا هر لیست مستقل مدیریت بشه.
-بهینهسازی حجم دادههای اپلیکیشن یکی از سختترین چالشها بود. ما باید حجم ریسپانس را طوری کاهش میدادیم که بدون از دست دادن اطلاعات حیاتی، به اندازهای کوچک بشه که معمولاً در یک سگمنت TCP منتقل بشه. وقتی داده در حجم پایین ارسال میشه، سرعت دریافت بالاتر، تأخیر کمتر و احتمال خطا نیز کمتر خواهد بود .البته در بعضی لحظات، حجم داده بیشتر از چند بایت میشد، ولی همون بهینهسازی برای چند ثانیهی طلایی فروش، تفاوت بزرگی ایجاد کرد.
- کش رو طوری تنظیم کردیم که هر لیست با سیاست خودش پاک بشه.
- یک مرحلهی میانی به رزرو اضافه کردیم تا متد اصلی سبکتر بمونه.
- در فرانتاند، مهمترین دغدغه نمایش درست و استفاده بهینه از ریسورس ها در دستگاهها بود. وقتی کاربر روی موبایل یا دسکتاپ وارد میشه، انتظار داره تجربهای روان و بینقص داشته باشه. این یعنی رندر شدن سریع صندلیها، الگوریتمهای دقیق برای جایگذاری صندلیها در حالتهای مختلف صفحه، و جلوگیری از افت کیفیت یا کندی. کوچکترین باگ در این بخش میتونست کل تجربه خرید رو خراب کنه
- در زیرساخت (DevOps)، پایداری و مانیتورینگ مهمترین بخش برای ما بود. آمادهسازی برای پیک ترافیک و مانیتورینگ لحظهای باعث شد حتی در اوج فشار، سامانه بدون مشکل کارش رو انجام بده.
- بخش مهم دیگه، انجام استرستستهای واقعی بود؛ جایی که با شبیهسازی بار سنگین روی سامانه، قبل از روز رویداد تمام نقاط ضعف احتمالی رو شناسایی و رفع کردیم. همین تستها باعث شد لحظهی اصلی، غافلگیر نشیم.
نتیجه؟
تمام ۲۸ هزار صندلی در کمتر از ۱۵ دقیقه سولد اوت شد، بدون اینکه تجربهی خرید کاربرها خدشهدار بشه.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15❤5👍1
🛡️ محافظت از فرم لاگین با Django-Defender
حملات brute-force 🔐 یکی از رایج ترین روشهای نفوذ به وبسایت ها هستند
جایی که هکرا با تلاشهای مکرر سعی میکنن رمز عبور کاربران را حدس بزنند.
کتابخانهی Django-Defender ⚡ ابزاری سبک، سریع و مطمئن برای مقابله با این حملات در پروژههای Django است.
✨ امکانات کلیدی
🚫 شمارش تلاشهای ناموفق ورود و بلاک کردن کاربر یا ip
⚡ استفاده از کش (Redis یا Memcached) برای عملکرد سریع
⏱️ امکان تنظیم تعداد تلاشهای مجاز و زمان بلاک (cool-off)
📊 ذخیره لاگها و مشاهده آنها در پنل مدیریت Django
🔐 بلاک بر اساس ip یا ترکیب یوزرنیم + ip
⚙️ نصب و راهاندازی
در settings.py تنظیمات پایه رو برای کانفیگ django defender اضافه کنید:
تنظیمات اصلی:
1⃣ DEFENDER_REDIS_URL :
مشخص میکنه داده های تلاش نا موفق کجا ذخیره میشن "redis://127.0.0.1:6379/0" یعنی Redis روی لوکال با پورت 6379 ودیتابیس شماره 0 اجرا بشه.
2⃣ DEFENDER_LOGIN_FAILURE_LIMIT:
تعداد دفعاتی که یک کاربر یا ip میتونه رمز اشتباه وارد کنه قبل از اینکه بلاک شه.
مثال: مقدار ۵ → بعد از ۵ تلاش ناموفق، بلاک فعال میشه
3⃣ DEFENDER_COOLOFF_TIME :
مدت زمان بلاک به ثانیه.
به عنوان مثال اینجا ۳۰۰ ثانیه یعنی بعد از بلاک شدن؛کاربر یا ip برای ۵ دقیقه نمیتونه لاگین کنه
4⃣ DEFENDER_LOCK_OUT_BY_COMBINATION_USER_AND_IP :
تعیین میکنه که مکانیزم بلاک چگونه عمل کنه و معیار محدودسازی کاربران چی باشه. مثلا وقتی متغیر روی True تنظیم شه، بلاک بر اساس ترکیب یوزرنیم و ip اعمال میشه؛ یعنی حتی اگر کاربر از یک ip جدید وارد شه، اگر همان یوزرنیم را استفاده کنه همچنان محدود خواهد بود و اجازه ورود نداره. اگر این متغیر روی False باشه، بلاک فقط بر اساس ip اعمال میشود و یوزرنیم میتونه از ip دیگر بدون مشکل وارد شه. این تنظیم باعث افزایش دقت امنیتی و جلوگیری از دور زدن محدودیتها توسط تغییر ip میشود.
5⃣ DEFENDER_STORE_FAILURES :
اگر True باشه، تلاشهای ناموفق در دیتابیس ذخیره میشن و میتونیم اونارو را تو پنل ادمین ببینیم
این ویژگی کمک میکند تحلیل و بررسی حملات راحت تر باشد
مایگریشن ها رو اجرا کنید:
🧪 تست عملکرد
5 بار با اطلاعات اشتباه سعی کنید داخل پروژه جنگویی خودتون لاگین کنید 🔑
پس از رسیدن به تعداد تلاشهای مجاز، دسترسی موقت بلاک خواهد شد 🚫
لاگها در پنل مدیریت ذخیره میشوند 📊
با فعال بودن LOCK_OUT_BY_COMBINATION_USER_AND_IP، حتی با IP جدید همان یوزرنیم بلاک خواهد شد 🔒
🎯 نتیجه:
اعمال چند خط تنظیمات ساده در Django-Defender، امنیت فرم لاگین پروژه شما به شکل چشمگیری افزایش مییابد. این ابزار به طور مؤثر جلوی حملات brute-force را میگیرد، تلاشهای ناموفق کاربران را ردیابی میکند و امکان مسدودسازی موقت ip یا یوزرنیم را فراهم میکند. با ذخیره لاگها در دیتابیس و بررسی آنها در پنل مدیریت، میتوانید فعالیتهای مشکوک را شناسایی کرده و امنیت کلی سایت خود را ارتقا دهید. به این ترتیب کنترل کامل بر دسترسی کاربران و حفاظت از حسابها برای شما ساده و قابل اطمینان خواهد بود ✅
✍ @Django_Experience
حملات brute-force 🔐 یکی از رایج ترین روشهای نفوذ به وبسایت ها هستند
جایی که هکرا با تلاشهای مکرر سعی میکنن رمز عبور کاربران را حدس بزنند.
کتابخانهی Django-Defender ⚡ ابزاری سبک، سریع و مطمئن برای مقابله با این حملات در پروژههای Django است.
✨ امکانات کلیدی
🚫 شمارش تلاشهای ناموفق ورود و بلاک کردن کاربر یا ip
⚡ استفاده از کش (Redis یا Memcached) برای عملکرد سریع
⏱️ امکان تنظیم تعداد تلاشهای مجاز و زمان بلاک (cool-off)
📊 ذخیره لاگها و مشاهده آنها در پنل مدیریت Django
🔐 بلاک بر اساس ip یا ترکیب یوزرنیم + ip
⚙️ نصب و راهاندازی
pip install django-defender
در settings.py تنظیمات پایه رو برای کانفیگ django defender اضافه کنید:
INSTALLED_APPS = [
...,
"defender",
]
MIDDLEWARE = [
...,
"defender.middleware.FailedLoginMiddleware",
]
تنظیمات اصلی:
DEFENDER_REDIS_URL = "redis://127.0.0.1:6379/0"
DEFENDER_LOGIN_FAILURE_LIMIT = 5
DEFENDER_COOLOFF_TIME = 300
DEFENDER_LOCK_OUT_BY_COMBINATION_USER_AND_IP = True
DEFENDER_STORE_FAILURES = True
1⃣ DEFENDER_REDIS_URL :
مشخص میکنه داده های تلاش نا موفق کجا ذخیره میشن "redis://127.0.0.1:6379/0" یعنی Redis روی لوکال با پورت 6379 ودیتابیس شماره 0 اجرا بشه.
2⃣ DEFENDER_LOGIN_FAILURE_LIMIT:
تعداد دفعاتی که یک کاربر یا ip میتونه رمز اشتباه وارد کنه قبل از اینکه بلاک شه.
مثال: مقدار ۵ → بعد از ۵ تلاش ناموفق، بلاک فعال میشه
3⃣ DEFENDER_COOLOFF_TIME :
مدت زمان بلاک به ثانیه.
به عنوان مثال اینجا ۳۰۰ ثانیه یعنی بعد از بلاک شدن؛کاربر یا ip برای ۵ دقیقه نمیتونه لاگین کنه
4⃣ DEFENDER_LOCK_OUT_BY_COMBINATION_USER_AND_IP :
تعیین میکنه که مکانیزم بلاک چگونه عمل کنه و معیار محدودسازی کاربران چی باشه. مثلا وقتی متغیر روی True تنظیم شه، بلاک بر اساس ترکیب یوزرنیم و ip اعمال میشه؛ یعنی حتی اگر کاربر از یک ip جدید وارد شه، اگر همان یوزرنیم را استفاده کنه همچنان محدود خواهد بود و اجازه ورود نداره. اگر این متغیر روی False باشه، بلاک فقط بر اساس ip اعمال میشود و یوزرنیم میتونه از ip دیگر بدون مشکل وارد شه. این تنظیم باعث افزایش دقت امنیتی و جلوگیری از دور زدن محدودیتها توسط تغییر ip میشود.
5⃣ DEFENDER_STORE_FAILURES :
اگر True باشه، تلاشهای ناموفق در دیتابیس ذخیره میشن و میتونیم اونارو را تو پنل ادمین ببینیم
این ویژگی کمک میکند تحلیل و بررسی حملات راحت تر باشد
مایگریشن ها رو اجرا کنید:
python manage.py migrate
🧪 تست عملکرد
5 بار با اطلاعات اشتباه سعی کنید داخل پروژه جنگویی خودتون لاگین کنید 🔑
پس از رسیدن به تعداد تلاشهای مجاز، دسترسی موقت بلاک خواهد شد 🚫
لاگها در پنل مدیریت ذخیره میشوند 📊
با فعال بودن LOCK_OUT_BY_COMBINATION_USER_AND_IP، حتی با IP جدید همان یوزرنیم بلاک خواهد شد 🔒
🎯 نتیجه:
اعمال چند خط تنظیمات ساده در Django-Defender، امنیت فرم لاگین پروژه شما به شکل چشمگیری افزایش مییابد. این ابزار به طور مؤثر جلوی حملات brute-force را میگیرد، تلاشهای ناموفق کاربران را ردیابی میکند و امکان مسدودسازی موقت ip یا یوزرنیم را فراهم میکند. با ذخیره لاگها در دیتابیس و بررسی آنها در پنل مدیریت، میتوانید فعالیتهای مشکوک را شناسایی کرده و امنیت کلی سایت خود را ارتقا دهید. به این ترتیب کنترل کامل بر دسترسی کاربران و حفاظت از حسابها برای شما ساده و قابل اطمینان خواهد بود ✅
✍ @Django_Experience
👏17❤6👍4✍1
Forwarded from Security Analysis
⭕️ حساب NPM یه توسعهدهنده معروف هک شده و پکیجهاش که بیش از 1 میلیارد بار دانلود شدن، ممکنه کل اکوسیستم جاوااسکریپت رو به خطر بندازه. بدافزار بهصورت مخفیانه آدرسهای کریپتو رو عوض میکنه و پول شما رو میزنه به حساب هکر!
اگه کیف پول سختافزاری دارید، قبل از زدن دکمه تایید، حتماً همه جزئیات تراکنش رو چک کنید.
نکته جالب این هک اینه که آدرس کیف پول کاربر با یکی از آدرسهای هکر جایگزین میشه، اما نه به صورت تصادفی، از الگوریتم Levenshtein Distance استفاده میکنه تا آدرس جایگزین شبیهترین به آدرس اصلی باشد.
جزئیات بیشتر :
jdstaerk.substack.com/p/we-just-found-malicious-code-in-the
#crypto #NPM #Wallet
@securation
اگه کیف پول سختافزاری دارید، قبل از زدن دکمه تایید، حتماً همه جزئیات تراکنش رو چک کنید.
نکته جالب این هک اینه که آدرس کیف پول کاربر با یکی از آدرسهای هکر جایگزین میشه، اما نه به صورت تصادفی، از الگوریتم Levenshtein Distance استفاده میکنه تا آدرس جایگزین شبیهترین به آدرس اصلی باشد.
جزئیات بیشتر :
jdstaerk.substack.com/p/we-just-found-malicious-code-in-the
#crypto #NPM #Wallet
@securation
❤3🤔3
با لود نشدن فایل های استاتیک و سرو کردنشون توی وب سرور مشکل دارید؟ و هر بار یادتون میره راه درستش چیه؟
Final Results
52%
آره خیلی رو مخه
9%
نه. من یه چیزی رو یه بار یاد بگیرم، دیگه تمامه
12%
آخرین بار که باهاش سر و کله زدم، قلقش دستم اومد
27%
محتوا نداشتی اینو گذاشتی؟
😁10
امروز یکسری حالات مختلف از teardown کردن تستها در pytest یاد گرفتم خوب بود هر کدوم کاربرد و جای خودش داره.
به سه حالت مختلف رسیدم. حالت اول زمانی که شما نیاز به یک resource دارید برای تستهاتون برای مثال اول لاگین کنید و بعدش ریکوئست بزنید. تو این مواقع بهتر که یک fixture داشته باشید که براتون لاگین کنه و وقتی کارتون تموم شد خودش لاگ اوت کنه.
به اون پروسه لاگاوت کردن میگن teardown یکدونه هم tear up داریم که پروسه لاگین کردن تو این مثاله. مثال دیگش میشه زمانی که نیاز دارید یک رکورد خاص داخل دیتابیس ساخته بشه و بعد از تست حذف بشه. به ساختنش میگن tear up به حذف کردنش میگن tear down.
خب حالا حالت اول که fixture باشه.
داخل فیکسچرها pytest هرچیزی که بعد از yield بیارید tear down و هرچی که قبلش بیاد tear up.
حالت دوم شما یک مقدار از درون تست نیاز دارید برای tear down کردن. برای مثال شما یک تست دارید پست زدن داخل توییتر رو تست میکنه. شما برای tear down کردن این تست لازم دارید پست رو پاک کنید اما برای پاک کردنش نیاز به id اون پست دارید. اینجاس که شما یک مقدار لازم دارید که داخل خود تست ساخته شده.
برای این مورد به نظر من بهترین حالت در حال حاضر با دانش الان من استفاده از try-finally هستش.
اینجا فیکسچرهای شما که برای مثال twt_client هست براتون کلاین tear up و tear down میکنن به روش اول. و try-finally پستی که ساختید رو tear down میکنه. مهدی سینیور ما باشد گفت که یک فیکسچر بسازم که داخلش یک yeild خالی باشه و بعد از yeild از داخل یک متغیر گلوبال بیاد ایدی پست ها رو بخونه و همرو حذف کنه که برای این کار لازمه داخل هر تست هر وقت پست ساختیم اضافه اش کنید به اون متغیر که من به نظرم try finally بهتر بود در نتیجه همون زدم فرستادم تکلید :)
✍🏻 @TorhamDevCH
به سه حالت مختلف رسیدم. حالت اول زمانی که شما نیاز به یک resource دارید برای تستهاتون برای مثال اول لاگین کنید و بعدش ریکوئست بزنید. تو این مواقع بهتر که یک fixture داشته باشید که براتون لاگین کنه و وقتی کارتون تموم شد خودش لاگ اوت کنه.
به اون پروسه لاگاوت کردن میگن teardown یکدونه هم tear up داریم که پروسه لاگین کردن تو این مثاله. مثال دیگش میشه زمانی که نیاز دارید یک رکورد خاص داخل دیتابیس ساخته بشه و بعد از تست حذف بشه. به ساختنش میگن tear up به حذف کردنش میگن tear down.
خب حالا حالت اول که fixture باشه.
import pytest
@pytest.fixture
def client() -> AuthedClient:
#login and etc
yeild client
client.logout()
داخل فیکسچرها pytest هرچیزی که بعد از yield بیارید tear down و هرچی که قبلش بیاد tear up.
حالت دوم شما یک مقدار از درون تست نیاز دارید برای tear down کردن. برای مثال شما یک تست دارید پست زدن داخل توییتر رو تست میکنه. شما برای tear down کردن این تست لازم دارید پست رو پاک کنید اما برای پاک کردنش نیاز به id اون پست دارید. اینجاس که شما یک مقدار لازم دارید که داخل خود تست ساخته شده.
برای این مورد به نظر من بهترین حالت در حال حاضر با دانش الان من استفاده از try-finally هستش.
def test_twt_post_create_success(twt_client):
post_id = None
try:
post = twt_client.post("Hello from test")
post_id = post.id
finally:
if post_id:
twt_client.remove_post(post_id)
اینجا فیکسچرهای شما که برای مثال twt_client هست براتون کلاین tear up و tear down میکنن به روش اول. و try-finally پستی که ساختید رو tear down میکنه. مهدی سینیور ما باشد گفت که یک فیکسچر بسازم که داخلش یک yeild خالی باشه و بعد از yeild از داخل یک متغیر گلوبال بیاد ایدی پست ها رو بخونه و همرو حذف کنه که برای این کار لازمه داخل هر تست هر وقت پست ساختیم اضافه اش کنید به اون متغیر که من به نظرم try finally بهتر بود در نتیجه همون زدم فرستادم تکلید :)
✍🏻 @TorhamDevCH
❤5👍1
خیلی تصادفی این رزومه رو دیدم توی لینکدین ، طرف برداشته رزومه شو در قالب ویندوز xp طراحی کرده، جذاب بود ایده ش :
https://mitchivin.com/
✍🏻 مسعود بیگی
https://mitchivin.com/
✍🏻 مسعود بیگی
🔥17❤3👍3
جنگولرن
با لود نشدن فایل های استاتیک و سرو کردنشون توی وب سرور مشکل دارید؟ و هر بار یادتون میره راه درستش چیه؟
نکته هایی در مورد فایل های استاتیک جنگو - بخش اول
داکیومنت محترم جنگو صراحتا گفته:
توی development (یعنی وقتی Debug=True هست) جنگو خودش فایل های استاتیک رو سرو میکنه.
به شرط اینکه اپ django.contrib.staticfiles توی INSTALLED_APPS باشه.
بعد گفته که STATIC_URL رو اینجوری تعریف کنید (پیش فرض اینه)
این چکار میکنه، هر وقت از تمپلت تگ static توی تمپلت ها استفاده می کنیم، مسیر فایل های استاتیک با این شروع میشه.
دقت کن آخرش یه اسلش هست، اگه آخرش اسلش رو نذاری، این خطارو میده و کلا پروژه ران نمیشه:
The STATIC_URL setting must end with a slash
خب حالا اگه این بخشی از تمپلت ما باشه، باید اول static رو لود کنیم. و بعدش از تمپلت تگ static استفاده کنیم:
جای اون static پایینی مسیر قرار میگیره.
مثلا سایتم ali.com باشه میشه:
ali.com/static/css/style.css
اگه اینارو میدونی یه 🥱 بزار
وگرنه هر چی دوس داری بزار 😅
ادامه دارد...
داکیومنت محترم جنگو صراحتا گفته:
توی development (یعنی وقتی Debug=True هست) جنگو خودش فایل های استاتیک رو سرو میکنه.
به شرط اینکه اپ django.contrib.staticfiles توی INSTALLED_APPS باشه.
بعد گفته که STATIC_URL رو اینجوری تعریف کنید (پیش فرض اینه)
STATIC_URL = "static/"
این چکار میکنه، هر وقت از تمپلت تگ static توی تمپلت ها استفاده می کنیم، مسیر فایل های استاتیک با این شروع میشه.
دقت کن آخرش یه اسلش هست، اگه آخرش اسلش رو نذاری، این خطارو میده و کلا پروژه ران نمیشه:
The STATIC_URL setting must end with a slash
خب حالا اگه این بخشی از تمپلت ما باشه، باید اول static رو لود کنیم. و بعدش از تمپلت تگ static استفاده کنیم:
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
جای اون static پایینی مسیر قرار میگیره.
مثلا سایتم ali.com باشه میشه:
ali.com/static/css/style.css
اگه اینارو میدونی یه 🥱 بزار
وگرنه هر چی دوس داری بزار 😅
ادامه دارد...
🥱46❤10🔥4
جنگولرن
با لود نشدن فایل های استاتیک و سرو کردنشون توی وب سرور مشکل دارید؟ و هر بار یادتون میره راه درستش چیه؟
نکته هایی در مورد فایل های استاتیک جنگو - بخش دوم
خب ما STATIC_URL رو مشخص کردیم.
حالا جنگو کجا باید دنبال فایل های استاتیک ما باشه؟
یکی از دوستان، توی کامنت ها نوشته:
جنگو انتظار داره هر app فایل های استاتیک خودش رو داشته باشه.
مثل اپ ع admin که اونم خودش یه فولدر به اسم static داره. و توی اون فولدر یه فولدر به اسم admin . استاتیک هاش اونجا هستن.
پس اگه اسم اپ ما shop هست. فایل های استاتیک اینجوری میشن:
shop/static/css/style.css
چرا؟
چون توی تمپلت اینجوری نوشته بودم، توی پست قبلی (بخش اول):
مثال داکیومنت جنگو اسم اپ رو توی تمپلت آورده (این مثالش):
و گفته فولدر ها باید اینجوری باشن، اسم اپ بعد static اومده:
my_app/static/my_app/example.jpg
✔️جنگو اول STATICFILES_DIRS رو میگرده بعد app هارو میگرده، یعنی اگه استایل مشترکی توی این فولدرها باشه، اولویت با STATICFILES_DIRS هست.
احتمالا کاربرد STATICFILES_DIRS رو متوجه شدید؟
بله، برای اینه که اگه فایل استاتیکی داریم که نمیخواهیم توی اپ خاصی باشه (مثلا دلیل مون اینه که مشترک هستن بین همه اپ ها)، پس توی این آرایه میزایمش، مثال جنگو اینه:
حالا یه نکته مهم:
✔️نباید STATIC_ROOT برابر با یکی از مسیرهای آرایه STATICFILES_DIRS باشه. وگرنه این خطارو میده:
The STATICFILES_DIRS setting should not contain the STATIC_ROOT setting
چرا؟
چون بعدا که میخواهیم دستور collectstatic رو اجرا کنیم، قاطی میکنه دیگه. چون این دستور همه static هارو یکجا جمع میکنه، که بدیم وب سرور serve شون کنه.
پس STATIC_ROOT برای مشخص کردن مسیر همه فایل های استاتیک، هنگام دیپلوی هست. (وقتی میخوایم پروژه رو ببریم روی اینترنت)
مقدار پیش فرض STATIC_ROOT برابر None هست. و اگه بخواهیم collectstatic کنیم باید بهش مقدار بدیم (اسم یا مسیر یه فولدر، اسلش آخرش هم نمیخواد 😁 )
زیاد شد، بقیه بعدا...
یه سوال بپرسم: چه زمانی لازمه اینکارو کنیم؟
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
اگه همه این نکات رو میدونستی یه 🥱
وگرنه هر چی دلت خواست
اسپانسر این پست 👈 لینک
خب ما STATIC_URL رو مشخص کردیم.
حالا جنگو کجا باید دنبال فایل های استاتیک ما باشه؟
یکی از دوستان، توی کامنت ها نوشته:
من دقیقا همینکارو میکنم لود نمیکنه
باید حتما تو
STATICFILES_DIRS
تعریف کنم تا لود شه
جنگو انتظار داره هر app فایل های استاتیک خودش رو داشته باشه.
مثل اپ ع admin که اونم خودش یه فولدر به اسم static داره. و توی اون فولدر یه فولدر به اسم admin . استاتیک هاش اونجا هستن.
پس اگه اسم اپ ما shop هست. فایل های استاتیک اینجوری میشن:
shop/static/css/style.css
چرا؟
چون توی تمپلت اینجوری نوشته بودم، توی پست قبلی (بخش اول):
href="{% static 'css/style.css' %}"
مثال داکیومنت جنگو اسم اپ رو توی تمپلت آورده (این مثالش):
{% load static %}
<img src="{% static 'my_app/example.jpg' %}" alt="My image">
و گفته فولدر ها باید اینجوری باشن، اسم اپ بعد static اومده:
my_app/static/my_app/example.jpg
✔️جنگو اول STATICFILES_DIRS رو میگرده بعد app هارو میگرده، یعنی اگه استایل مشترکی توی این فولدرها باشه، اولویت با STATICFILES_DIRS هست.
احتمالا کاربرد STATICFILES_DIRS رو متوجه شدید؟
بله، برای اینه که اگه فایل استاتیکی داریم که نمیخواهیم توی اپ خاصی باشه (مثلا دلیل مون اینه که مشترک هستن بین همه اپ ها)، پس توی این آرایه میزایمش، مثال جنگو اینه:
STATICFILES_DIRS = [
BASE_DIR / "static",
"/var/www/static/",
]
حالا یه نکته مهم:
✔️نباید STATIC_ROOT برابر با یکی از مسیرهای آرایه STATICFILES_DIRS باشه. وگرنه این خطارو میده:
The STATICFILES_DIRS setting should not contain the STATIC_ROOT setting
چرا؟
چون بعدا که میخواهیم دستور collectstatic رو اجرا کنیم، قاطی میکنه دیگه. چون این دستور همه static هارو یکجا جمع میکنه، که بدیم وب سرور serve شون کنه.
پس STATIC_ROOT برای مشخص کردن مسیر همه فایل های استاتیک، هنگام دیپلوی هست. (وقتی میخوایم پروژه رو ببریم روی اینترنت)
مقدار پیش فرض STATIC_ROOT برابر None هست. و اگه بخواهیم collectstatic کنیم باید بهش مقدار بدیم (اسم یا مسیر یه فولدر، اسلش آخرش هم نمیخواد 😁 )
زیاد شد، بقیه بعدا...
یه سوال بپرسم: چه زمانی لازمه اینکارو کنیم؟
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
اگه همه این نکات رو میدونستی یه 🥱
وگرنه هر چی دلت خواست
اسپانسر این پست 👈 لینک
🔥10👍5🥱4❤3