سید فرندز / برنامه نویسی / هک و امنیت / تکنولوژی
Voice message
نمیشه یه جاهایی ش رو بوووق بزارم
ولی نکته قابل تاملی میگه
ولی نکته قابل تاملی میگه
❤2
Forwarded from Learning With M
خیلی ها پرسیدن، تو که ۲۲ سال دات نت کار کردی، چرا الان java و golang و php؟
سوال خوبیه.
اگر ما مهندس نرم افزار هستیم، زبان میشه ابزار توسعه نرم افزار و هرچی باشه مهم نیست.
اگر برنامه نویس دات نت یا هر زبان دیگری هستیم و نمیخواهیم رهاش کنیم، میشیم برنامه نویس اون زبان.
برنامه نویسی ۳۰ الی ۴۰٪ مهندسی نرم افزاره.
نظر شخصیم اینه که : اگر به زبان برنامه نویسی خاصی وابستگی زیادی دارید، احتمالا به زودی AI با هزینه خیلی کمتر از انسان اونو برامون انجام خواهد داد، ولی اگر مهندسیتون رو تقویت کنید، AI قراره ۳۰ الی ۴۰% کارتون رو که همون برنامه نویسی باشه رو راحت تر کنه.
سوال خوبیه.
اگر ما مهندس نرم افزار هستیم، زبان میشه ابزار توسعه نرم افزار و هرچی باشه مهم نیست.
اگر برنامه نویس دات نت یا هر زبان دیگری هستیم و نمیخواهیم رهاش کنیم، میشیم برنامه نویس اون زبان.
برنامه نویسی ۳۰ الی ۴۰٪ مهندسی نرم افزاره.
نظر شخصیم اینه که : اگر به زبان برنامه نویسی خاصی وابستگی زیادی دارید، احتمالا به زودی AI با هزینه خیلی کمتر از انسان اونو برامون انجام خواهد داد، ولی اگر مهندسیتون رو تقویت کنید، AI قراره ۳۰ الی ۴۰% کارتون رو که همون برنامه نویسی باشه رو راحت تر کنه.
👍26❤5👎5👏2🤮1🥱1
اضافه کردن یک CustomValidator به ولیدیتور پسورد در پروژه جنگو
برای فیلد پسورد تعداد کاراکتر مشخص کرده و متن پیغامش هم فارسی نوشته و از دیکشنری و ترجمه کردن استفاده نشده
تشکر از عمو جی پی تی
برای فیلد پسورد تعداد کاراکتر مشخص کرده و متن پیغامش هم فارسی نوشته و از دیکشنری و ترجمه کردن استفاده نشده
تشکر از عمو جی پی تی
👍8❤1
ویو LogoutView از نسخه 5.0 جنگو به بعد فقط ریکوئست از نوع post رو قبول میکنه.
یعنی چی؟
یعنی دیگه با لینک دادن بهش لاگ اوت نمیشیم و خطای 405 می بینیم.
باید با post بفرستیم و csrf_token هم ارسال بشه.
این نمودار سلسله مراتب هم از سایت https://ccbv.co.uk/ گرفتم.
یعنی چی؟
یعنی دیگه با لینک دادن بهش لاگ اوت نمیشیم و خطای 405 می بینیم.
باید با post بفرستیم و csrf_token هم ارسال بشه.
این نمودار سلسله مراتب هم از سایت https://ccbv.co.uk/ گرفتم.
👍19😁5
Forwarded from علی بیگدلی
همدلیدر مسیر یادگیری
از اونجایی که قول داده بودم که با پلتفرم مکتبخونه پیگیر رایگان سازی دوره برای تعداد افراد بیشتری بشم. بالاخره این اتفاق افتاد و الان در طرح بزرگ همدلی مکتبخونه دو دوره جنگو مقدماتی و پیشرفته منو می تونین با ۱۰۰٪ تخفیف تهیه کنین. 😄🌷
باشد که این بار به دست همه نیازمنداش برسه و بتونن از یادگیری غافل نشن.
جنگو مقدماتی:
https://mktb.me/tgk5/
جنگو پیشرفته:
https://mktb.me/vmxs/
۱۰۰ تا دوره محبوب مکتبخونه رایگان شدن
توی حوزه های مختلف از برنامه و نویسی و شبکه و هوش مصنوعی تا مهارت های نرم و زبان و ...
کافیه دوره ها رو توی سبد خریدتون با برداشتن تیک (دوره کامل ) و فقط خرید محتوا اضافه کنین و کد HAMDELI رو وارد کنین و در این صورت می تونین به رایگان از دوره ها استفاده کنین.
از اونجایی که قول داده بودم که با پلتفرم مکتبخونه پیگیر رایگان سازی دوره برای تعداد افراد بیشتری بشم. بالاخره این اتفاق افتاد و الان در طرح بزرگ همدلی مکتبخونه دو دوره جنگو مقدماتی و پیشرفته منو می تونین با ۱۰۰٪ تخفیف تهیه کنین. 😄🌷
باشد که این بار به دست همه نیازمنداش برسه و بتونن از یادگیری غافل نشن.
جنگو مقدماتی:
https://mktb.me/tgk5/
جنگو پیشرفته:
https://mktb.me/vmxs/
۱۰۰ تا دوره محبوب مکتبخونه رایگان شدن
توی حوزه های مختلف از برنامه و نویسی و شبکه و هوش مصنوعی تا مهارت های نرم و زبان و ...
کافیه دوره ها رو توی سبد خریدتون با برداشتن تیک (دوره کامل ) و فقط خرید محتوا اضافه کنین و کد HAMDELI رو وارد کنین و در این صورت می تونین به رایگان از دوره ها استفاده کنین.
❤29👎2👍1
اگر می خواید AI جاتون رو نگیره سعی کنید Requirement Engineering رو یاد بگیرید و بفهمید.
یک کتاب خفن در موردش
Software Requirements Third Edition - Joy Beatty
متن بالا بخشی از یه پست کانال thisisnabi بود 😁
توضیحات chatgpt:
مهندسی نیازمندیها یا Requirement Engineering بخشی از فرآیند توسعه نرمافزار است که به شناسایی، تحلیل، مستندسازی و مدیریت نیازمندیهای سیستم میپردازد. هدف از این علم، اطمینان از این است که نرمافزار در نهایت به نیازها و خواستههای کاربران و ذینفعان پاسخ میدهد.
فرآیند مهندسی نیازمندیها معمولاً شامل مراحل زیر است:
1. شناسایی نیازمندیها**: در این مرحله، نیازمندیهای واقعی سیستم شناسایی میشوند. این کار معمولاً با جمعآوری اطلاعات از ذینفعان، مصاحبهها، کارگاهها و بررسی مستندات موجود انجام میشود.
2. تحلیل نیازمندیها**: نیازمندیها تحلیل و بررسی میشوند تا مشخص شود که آیا آنها قابل فهم، کامل، قابل اندازهگیری و قابل تحقق هستند یا خیر.
3. مستندسازی نیازمندیها**: نیازمندیها باید به شکل مستند و مطابق با استانداردهای مشخصی ثبت شوند تا در آینده بتوان به آنها مراجعه کرد.
4. تایید نیازمندیها**: پس از مستندسازی، نیازمندیها باید توسط ذینفعان تأیید شوند تا از صحت و تناسب آنها اطمینان حاصل شود.
5. مدیریت نیازمندیها**: نیازمندیها باید به طور مداوم مدیریت شوند تا تغییرات و اصلاحات لازم در طول فرآیند توسعه نرمافزار اعمال شوند.
مهندسی نیازمندیها به عنوان یکی از مراحل کلیدی در توسعه نرمافزار شناخته میشود و تأثیر زیادی بر کیفیت پروژه و رضایت مشتری دارد.
یک کتاب خفن در موردش
Software Requirements Third Edition - Joy Beatty
متن بالا بخشی از یه پست کانال thisisnabi بود 😁
توضیحات chatgpt:
مهندسی نیازمندیها یا Requirement Engineering بخشی از فرآیند توسعه نرمافزار است که به شناسایی، تحلیل، مستندسازی و مدیریت نیازمندیهای سیستم میپردازد. هدف از این علم، اطمینان از این است که نرمافزار در نهایت به نیازها و خواستههای کاربران و ذینفعان پاسخ میدهد.
فرآیند مهندسی نیازمندیها معمولاً شامل مراحل زیر است:
1. شناسایی نیازمندیها**: در این مرحله، نیازمندیهای واقعی سیستم شناسایی میشوند. این کار معمولاً با جمعآوری اطلاعات از ذینفعان، مصاحبهها، کارگاهها و بررسی مستندات موجود انجام میشود.
2. تحلیل نیازمندیها**: نیازمندیها تحلیل و بررسی میشوند تا مشخص شود که آیا آنها قابل فهم، کامل، قابل اندازهگیری و قابل تحقق هستند یا خیر.
3. مستندسازی نیازمندیها**: نیازمندیها باید به شکل مستند و مطابق با استانداردهای مشخصی ثبت شوند تا در آینده بتوان به آنها مراجعه کرد.
4. تایید نیازمندیها**: پس از مستندسازی، نیازمندیها باید توسط ذینفعان تأیید شوند تا از صحت و تناسب آنها اطمینان حاصل شود.
5. مدیریت نیازمندیها**: نیازمندیها باید به طور مداوم مدیریت شوند تا تغییرات و اصلاحات لازم در طول فرآیند توسعه نرمافزار اعمال شوند.
مهندسی نیازمندیها به عنوان یکی از مراحل کلیدی در توسعه نرمافزار شناخته میشود و تأثیر زیادی بر کیفیت پروژه و رضایت مشتری دارد.
✍10❤7👍4👎1👏1
Forwarded from Python BackendHub (Mani)
از کانال های مختلف دیدم پست میذارن که بله تایپینگ کد شما رو بیشتر میکنه کثیف تر میکنه اگه میخواستیم تایپ بزنیم که میرفتیم سمت C و این حرفا. اولا که C تایپ سیستم قوی نداره. تایپ سیستم بسیار ساده ای داره. پس statically typed بودن یا نبودن یک زبون رو خوب/بد بودن تایپ سیستمش تاثیری نمیذاره. پس اگه انتخابتون C هست برای اینکه تایپ سیستم قوی داشته باشین انتخاب درستی نیست!
ثانیا تایپینگ خودش یک داکیومنته. مثلا شما فکر کنید من یک سیستم نوشتم که ۱۰ تاسیستم مختلف رو integrate میکنه و یک API واحد میده برای هر ۱۰ تاشون. من یا میتونم ۱۰ صفحه داکیومنت بنویسم که اگه خواستیم یک سیستم جدید اضافه کنیم چه دپندسی هایی وجود داره یا اینکه میتونم یک Enum داشته باشم به اسم
مثالش, من اینجا فقط یک سرویس Digikala دارم. و برای دیجی کالا یک رفتاری رو تعریف کردم و چک کردم سرویسی نباشه که این رفتار براش تعریف نشده باشه (`assert_never`)
وقتی من یک سرویس جدید اضافه کنم به Enum ام اگه من کد رو کمپایل کنم یا تایپ چکر رو کد ران کنم و کدم کمپایل شه, کلی ارور تایپینگ میبینم که میگه شما این دپندنسی رو تعریف نکردی. مثل همین فانکشن. اون موقع به محض اینکه من تمام ایرادات تایپینگ رو برطرف کنم PRام تموم شده.
کد خواناییشو از دست میده؟ نه واقعا!شما اگه خوانایی کد رو به تعداد خط ملاک قرار میدین, پس کد ننویسید که خیلی خوانا و تمیز باشه. کد خوانا یعنی من کدی رو بخونم و بفهمم چیکار میکنه و constraint های اون کد چیه و تو موقع استفاده ازش اشتباه نکنم.
یک مثال دیگه بازم تو پست بعدی میزنم
@PyBackendHub
ثانیا تایپینگ خودش یک داکیومنته. مثلا شما فکر کنید من یک سیستم نوشتم که ۱۰ تاسیستم مختلف رو integrate میکنه و یک API واحد میده برای هر ۱۰ تاشون. من یا میتونم ۱۰ صفحه داکیومنت بنویسم که اگه خواستیم یک سیستم جدید اضافه کنیم چه دپندسی هایی وجود داره یا اینکه میتونم یک Enum داشته باشم به اسم
Service
و همه جا با اون Enum بیام exhaustive check انجام بدم.مثالش, من اینجا فقط یک سرویس Digikala دارم. و برای دیجی کالا یک رفتاری رو تعریف کردم و چک کردم سرویسی نباشه که این رفتار براش تعریف نشده باشه (`assert_never`)
def do_foo(service: Service):
match service:
case Service.DIGI_KALA: ...
case _: assert_never(service)
وقتی من یک سرویس جدید اضافه کنم به Enum ام اگه من کد رو کمپایل کنم یا تایپ چکر رو کد ران کنم و کدم کمپایل شه, کلی ارور تایپینگ میبینم که میگه شما این دپندنسی رو تعریف نکردی. مثل همین فانکشن. اون موقع به محض اینکه من تمام ایرادات تایپینگ رو برطرف کنم PRام تموم شده.
کد خواناییشو از دست میده؟ نه واقعا!شما اگه خوانایی کد رو به تعداد خط ملاک قرار میدین, پس کد ننویسید که خیلی خوانا و تمیز باشه. کد خوانا یعنی من کدی رو بخونم و بفهمم چیکار میکنه و constraint های اون کد چیه و تو موقع استفاده ازش اشتباه نکنم.
یک مثال دیگه بازم تو پست بعدی میزنم
@PyBackendHub
❤7👍1👎1
سید فرندز / برنامه نویسی / هک و امنیت / تکنولوژی
Voice message
فکر نکنید پست قبلی به این جواب داده
👎3❤2😁2
داشتم یه مدل میساختم که باید برای یه فیلدش چند مقدار مشخص تعریف میکردم.
طبق عادت قدیمی، رفتم یه لیست (value, label) بسازم… ولی وسط کار چشمم افتاد به models.TextChoices
گفتم خب، یه بار امتحانش کنم… و از همون لحظه فهمیدم این بهترین راهه برای تعریف choice field تو Django
مزیتهاش چیه؟
به جای "info" میگی Level.INFO → هم امنتره، هم IDE بهت autocomplete میده.
مقدار دیتابیس و برچسب نمایشی رو با هم داری.
میتونی با obj.get_level_display() اسم قابل نمایش رو بگیری.
کد ساختاریافته تره
وقتی میشه کد تمیزتر و قابل نگهداریتری داشت، چرا هنوز با استرینگ خام کار کنیم؟ 😉
از لینکدین شایان حسین زاده
طبق عادت قدیمی، رفتم یه لیست (value, label) بسازم… ولی وسط کار چشمم افتاد به models.TextChoices
گفتم خب، یه بار امتحانش کنم… و از همون لحظه فهمیدم این بهترین راهه برای تعریف choice field تو Django
مزیتهاش چیه؟
به جای "info" میگی Level.INFO → هم امنتره، هم IDE بهت autocomplete میده.
مقدار دیتابیس و برچسب نمایشی رو با هم داری.
میتونی با obj.get_level_display() اسم قابل نمایش رو بگیری.
کد ساختاریافته تره
وقتی میشه کد تمیزتر و قابل نگهداریتری داشت، چرا هنوز با استرینگ خام کار کنیم؟ 😉
از لینکدین شایان حسین زاده
👍12❤3👎1
چرا جنگو رو یاد گرفتی؟
Anonymous Poll
11%
باهاش کارمند بشم
19%
پروژه های فریلنسری باهاش انجام بدم
28%
هم فریلنسری هم کارمندی
15%
از سر بیکاری
28%
یه اشتباهی بود کردیم دیگه
19%
موارد دیگه
😁19👎1
امنیت پایدارتر با یک چرخش ساده! 😎
✅ اگه با JWT کار کرده باشی، میدونی که ما یک access token و یک refresh token داریم
✅ اکسس توکن ما که خب عمرش کوتاهه مثلا بعد 10 دقیقه باطل میشه و از طریق رفرش توکن که عمرش بلندتره(مثلا 7 روز) باید یک اکسس توکن و رفرش توکن جدید از سرور درخواست کنیم
🤨 حالا یک مسعله ای هست این وسط ؟!
رفرش توکن شما نباید اینطوری باشه که توی اون 7 روز هربار که ازش استفاده کردی فرت و فرت بهت اکسس توکن بده.
😈 اینطوری اگه هکر عزیز بنا به هر علتی به اون رفرش توکن دسترسی پیدا کنه توی اون 7 روز هزاربار میتونه token بگیره و عشق و حال کنه
☝🏻اینجا دوتا مفهوم داریم به اسم rotate refresh token
و revoke refresh token که خیلی شبیه هم هستن(با فرق کوچولو)
✅ Rotate Token
یعنی هر بار که کاربر از Refresh Token استفاده کرد، یه Access Token جدید و یه Refresh Token جدید صادر میکنیم.
توی این حالت، Refresh Token قبلی دیگه نباید قابل استفاده باشه
اینجوریه که میگه: تو بیا رفرش توکن رو توی یک جایی مثلا ردیس یا هرچی، ذخیره کن و وقتی کاربر از اون رفرش توکن استفاده کرد قبلی رو حذف کن و جدیده رو بزار جاش تا یکبار بیشتر نتونه استفاده کنه
✅ Revoke Token
یعنی بیاعتبار کردن یک توکن قبل از اینکه تاریخ انقضاش برسه(با expire طبیعی توکن اشتباه نگیری). مثلا وقتی کاربر logout میکنه یا Refresh Token جدید گرفته، Refresh Token قبلی رو revoke میکنیم.
✅ در واقع میشه یه جورایی گفت :
اRotate یعنی "توکن جدید بده و قبلی رو کنار بذار"
اRevoke یعنی "توکن فعلی رو از کار بنداز"
این لینک زیر هم خیلی مفصل تر توضیح داده
https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
از تلگرام @LearnByLearn
✅ اگه با JWT کار کرده باشی، میدونی که ما یک access token و یک refresh token داریم
✅ اکسس توکن ما که خب عمرش کوتاهه مثلا بعد 10 دقیقه باطل میشه و از طریق رفرش توکن که عمرش بلندتره(مثلا 7 روز) باید یک اکسس توکن و رفرش توکن جدید از سرور درخواست کنیم
🤨 حالا یک مسعله ای هست این وسط ؟!
رفرش توکن شما نباید اینطوری باشه که توی اون 7 روز هربار که ازش استفاده کردی فرت و فرت بهت اکسس توکن بده.
😈 اینطوری اگه هکر عزیز بنا به هر علتی به اون رفرش توکن دسترسی پیدا کنه توی اون 7 روز هزاربار میتونه token بگیره و عشق و حال کنه
☝🏻اینجا دوتا مفهوم داریم به اسم rotate refresh token
و revoke refresh token که خیلی شبیه هم هستن(با فرق کوچولو)
✅ Rotate Token
یعنی هر بار که کاربر از Refresh Token استفاده کرد، یه Access Token جدید و یه Refresh Token جدید صادر میکنیم.
توی این حالت، Refresh Token قبلی دیگه نباید قابل استفاده باشه
اینجوریه که میگه: تو بیا رفرش توکن رو توی یک جایی مثلا ردیس یا هرچی، ذخیره کن و وقتی کاربر از اون رفرش توکن استفاده کرد قبلی رو حذف کن و جدیده رو بزار جاش تا یکبار بیشتر نتونه استفاده کنه
✅ Revoke Token
یعنی بیاعتبار کردن یک توکن قبل از اینکه تاریخ انقضاش برسه(با expire طبیعی توکن اشتباه نگیری). مثلا وقتی کاربر logout میکنه یا Refresh Token جدید گرفته، Refresh Token قبلی رو revoke میکنیم.
✅ در واقع میشه یه جورایی گفت :
اRotate یعنی "توکن جدید بده و قبلی رو کنار بذار"
اRevoke یعنی "توکن فعلی رو از کار بنداز"
این لینک زیر هم خیلی مفصل تر توضیح داده
https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
از تلگرام @LearnByLearn
✍18❤6👍5👏2🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
وقتی یه نفر میگه: تو که کارت راحته، فقط نشستی پشت میز پای لپتاپ 😁😅
👍8😁4👎1
✅ هندل کردن Open Redirect Attack توی جنگو با RedirectURLMixin
این Open Redirect Attack چیه؟ کلمه این رو گذاشتم اولش راست چین بشه 😁
وقتی شما کاربر رو به URL بیرونی ریدایرکت میکنید بدون بررسی، یه attacker میتونه ازش سوء استفاده کنه:
https://yoursite.com/login/?next=https://hack.com
کاربر فکر میکنه داره به سایت شما میره، ولی بعد از login به سایت مهاجم هدایت میشه. این میتونه phishing یا سرقت اطلاعات session کاربر رو ممکن کنه. (من بلد نیستم چطوری میتونه، خودتون سرچ کنید)
میکسین ع RedirectURLMixin توی جنگو (django.contrib.auth.views) جلوی این حرکت رو می گیره. (یکی از کارهاش اینه)
چی کار میکنه؟
با میکسین ع RedirectURLMixin می تونیم بررسی کنیم که این URL جزو hostهای مجاز هست.
یه مثال ساده براش:
اون get_redirect_url یکی از متدهای این میکسین ع
حالا من اگه آدرس رو اینجوری بدم:
https://127.0.0.1:8000/profiles/aaa/?next=https://djangolearn.ir/
ریدارکت میشه به صفحه اصلی سایت خودتون نه سایت جنگولرن 😁
راستی از نسخه 4.1 به بعد این میکسین جایگزین SuccessURLAllowedHostsMixin شده:
The undocumented django.contrib.auth.views.SuccessURLAllowedHostsMixin mixin is replaced by RedirectURLMixin.
لایک نداشت این پست؟
این Open Redirect Attack چیه؟ کلمه این رو گذاشتم اولش راست چین بشه 😁
وقتی شما کاربر رو به URL بیرونی ریدایرکت میکنید بدون بررسی، یه attacker میتونه ازش سوء استفاده کنه:
https://yoursite.com/login/?next=https://hack.com
کاربر فکر میکنه داره به سایت شما میره، ولی بعد از login به سایت مهاجم هدایت میشه. این میتونه phishing یا سرقت اطلاعات session کاربر رو ممکن کنه. (من بلد نیستم چطوری میتونه، خودتون سرچ کنید)
میکسین ع RedirectURLMixin توی جنگو (django.contrib.auth.views) جلوی این حرکت رو می گیره. (یکی از کارهاش اینه)
چی کار میکنه؟
با میکسین ع RedirectURLMixin می تونیم بررسی کنیم که این URL جزو hostهای مجاز هست.
یه مثال ساده براش:
class AAA(RedirectURLMixin, View):
redirect_field_name = "next"
def get(self, request, *args, **kwargs):
url = self.get_redirect_url()
if url:
return redirect(url)
return redirect("/")
اون get_redirect_url یکی از متدهای این میکسین ع
حالا من اگه آدرس رو اینجوری بدم:
https://127.0.0.1:8000/profiles/aaa/?next=https://djangolearn.ir/
ریدارکت میشه به صفحه اصلی سایت خودتون نه سایت جنگولرن 😁
راستی از نسخه 4.1 به بعد این میکسین جایگزین SuccessURLAllowedHostsMixin شده:
The undocumented django.contrib.auth.views.SuccessURLAllowedHostsMixin mixin is replaced by RedirectURLMixin.
لایک نداشت این پست؟
❤31👍11😁1
سوال:
شما اسلایدر برای سایت تون چطوری می سازید؟
این پیشنهاد chatgpt بود:
اگه میخوای اسلایدرت خیلی انعطافپذیر باشه، میتونی از GenericForeignKey استفاده کنی که به هر مدل وصل بشه (محصول، مقاله، دستهبندی و …).
مزایا:
نهایت انعطافپذیری: میتونی هر چیزی رو توی اسلایدر بذاری.
آیندهنگر و تمیز.
معایب:
کار باهاش پیچیدهتره.
برای خیلی از پروژههای معمولی زیادی Over-Engineering محسوب میشه.
شما اسلایدر برای سایت تون چطوری می سازید؟
این پیشنهاد chatgpt بود:
اگه میخوای اسلایدرت خیلی انعطافپذیر باشه، میتونی از GenericForeignKey استفاده کنی که به هر مدل وصل بشه (محصول، مقاله، دستهبندی و …).
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Slider(models.Model):
title = models.CharField(max_length=255, blank=True)
image = models.ImageField(upload_to="sliders/")
url = models.URLField(blank=True, null=True)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, null=True, blank=True)
object_id = models.PositiveIntegerField(null=True, blank=True)
content_object = GenericForeignKey('content_type', 'object_id')
order = models.PositiveIntegerField(default=0)
is_active = models.BooleanField(default=True)
مزایا:
نهایت انعطافپذیری: میتونی هر چیزی رو توی اسلایدر بذاری.
آیندهنگر و تمیز.
معایب:
کار باهاش پیچیدهتره.
برای خیلی از پروژههای معمولی زیادی Over-Engineering محسوب میشه.
❤9👍1🤔1
جنگولرن
سوال: شما اسلایدر برای سایت تون چطوری می سازید؟ این پیشنهاد chatgpt بود: اگه میخوای اسلایدرت خیلی انعطافپذیر باشه، میتونی از GenericForeignKey استفاده کنی که به هر مدل وصل بشه (محصول، مقاله، دستهبندی و …). from django.contrib.contenttypes.fields import…
پیرو پست قبلی، یکی پرسید اون ContentType چیه و کارش چیه؟
اگه دقت کرده باشید توی INSTALLED_APPS یه اپ هست به اسم django.contrib.contenttypes و به واسطه این وقتی migrate می کنید، یه جدول به اسم django_content_type ساخته میشه. که همه مدل های پروژه رو توش نگهداری می کنه.
حالا اگه این لینک رو ببینید:
https://docs.djangoproject.com/en/5.2/ref/contrib/contenttypes/#generic-relations
درباره جنریک ریلیشن توضیح داده یا GenericForeignKey که اشاره میکنه به content_type
مزیت ش چیه این جنریک ریلیشن؟
یک مثال از chatgpt برای comment :
فرض کن میخوای یه سیستم کامنت داشته باشی.
کاربر میتونه روی محصول کامنت بذاره.
یا روی پست بلاگ.
یا روی سفارش.
راه سنتی (بدون Generic):
یا باید برای هر مدل یه فیلد ForeignKey بسازی:
👉 مشکل: کلی فیلد خالی داری و هر بار باید کد اضافه بزنی.
یا باید برای هر مدل یه مدل کامنت جدا بسازی (CommentForProduct, CommentForBlog, ...).
👉 مشکل: کلی جدول و کد تکراری.
📌 راه حل با Generic Relation
به جای این همه دردسر، با GenericForeignKey یه بار تعریف میکنی:
حالا content_object میتونه هر چیزی باشه (Product، Blog، Order و ...).
✅ مزیتهای Generic Relation
سادگی و انعطافپذیری: فقط یه جدول داری که میتونه به همهچی وصل بشه.
کاهش کد تکراری: به جای نوشتن چند مدل/فیلد مختلف، یه بار تعریف میکنی و برای همه استفاده میشه.
افزودن مدلهای جدید بدون تغییر دیتابیس: مثلاً اگه فردا خواستی روی Category هم کامنت بذاری، لازم نیست مدل Comment رو تغییر بدی؛ همون GenericForeignKey جواب میده.
یکپارچگی دادهها:همه کامنتها/لایکها/اکتیویتیها توی یه جدول جمع میشه → مدیریت و جستجو راحتتر.
⚠️ معایبش
کمی پیچیدگی بیشتر در Queryها (چون باید از ContentType کمک بگیری).
enforce کردن روابط در سطح دیتابیس سختتره (چون DB نمیدونه object_id دقیقاً به کدوم جدول اشاره میکنه).
اگه دقت کرده باشید توی INSTALLED_APPS یه اپ هست به اسم django.contrib.contenttypes و به واسطه این وقتی migrate می کنید، یه جدول به اسم django_content_type ساخته میشه. که همه مدل های پروژه رو توش نگهداری می کنه.
حالا اگه این لینک رو ببینید:
https://docs.djangoproject.com/en/5.2/ref/contrib/contenttypes/#generic-relations
درباره جنریک ریلیشن توضیح داده یا GenericForeignKey که اشاره میکنه به content_type
مزیت ش چیه این جنریک ریلیشن؟
یک مثال از chatgpt برای comment :
فرض کن میخوای یه سیستم کامنت داشته باشی.
کاربر میتونه روی محصول کامنت بذاره.
یا روی پست بلاگ.
یا روی سفارش.
راه سنتی (بدون Generic):
یا باید برای هر مدل یه فیلد ForeignKey بسازی:
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, null=True, blank=True, on_delete=models.CASCADE)
blog = models.ForeignKey(Blog, null=True, blank=True, on_delete=models.CASCADE)
order = models.ForeignKey(Order, null=True, blank=True, on_delete=models.CASCADE)
👉 مشکل: کلی فیلد خالی داری و هر بار باید کد اضافه بزنی.
یا باید برای هر مدل یه مدل کامنت جدا بسازی (CommentForProduct, CommentForBlog, ...).
👉 مشکل: کلی جدول و کد تکراری.
📌 راه حل با Generic Relation
به جای این همه دردسر، با GenericForeignKey یه بار تعریف میکنی:
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
text = models.TextField()
حالا content_object میتونه هر چیزی باشه (Product، Blog، Order و ...).
✅ مزیتهای Generic Relation
سادگی و انعطافپذیری: فقط یه جدول داری که میتونه به همهچی وصل بشه.
کاهش کد تکراری: به جای نوشتن چند مدل/فیلد مختلف، یه بار تعریف میکنی و برای همه استفاده میشه.
افزودن مدلهای جدید بدون تغییر دیتابیس: مثلاً اگه فردا خواستی روی Category هم کامنت بذاری، لازم نیست مدل Comment رو تغییر بدی؛ همون GenericForeignKey جواب میده.
یکپارچگی دادهها:همه کامنتها/لایکها/اکتیویتیها توی یه جدول جمع میشه → مدیریت و جستجو راحتتر.
⚠️ معایبش
کمی پیچیدگی بیشتر در Queryها (چون باید از ContentType کمک بگیری).
enforce کردن روابط در سطح دیتابیس سختتره (چون DB نمیدونه object_id دقیقاً به کدوم جدول اشاره میکنه).
❤7👍6
می دونستید ممکنه unique_together در آینده توی جنگو منسوخ بشه؟
البته از جنگو 2.2 به بعد داره میگه در آینده ممکنه منسوخ بشه 😁
لینک:
https://docs.djangoproject.com/en/5.2/ref/models/options/#django.db.models.Options.unique_together
خود داکیومنت جنگو گفته بهتره از UniqueConstraint استفاده کنید:
لینک:
https://docs.djangoproject.com/en/5.2/ref/models/constraints/#django.db.models.UniqueConstraint
یه مثال:
فرض کن میخواهیم ترکیب محصول و رنگ فقط یکی باشه، قبلا اینجوری می نوشتیم:
توی UniqueConstraint اینجوریه:
تازه میتونیم بگیم در شرایطی خاص این حالت فعال باشه.
خودتون زحمت بکشید condition رو توی لینکی که دادم سرچ کنید.
قابلیت های دیگه ای هم داره، که بازم خودتون...
و من الله التوفیق
البته از جنگو 2.2 به بعد داره میگه در آینده ممکنه منسوخ بشه 😁
لینک:
https://docs.djangoproject.com/en/5.2/ref/models/options/#django.db.models.Options.unique_together
خود داکیومنت جنگو گفته بهتره از UniqueConstraint استفاده کنید:
لینک:
https://docs.djangoproject.com/en/5.2/ref/models/constraints/#django.db.models.UniqueConstraint
یه مثال:
فرض کن میخواهیم ترکیب محصول و رنگ فقط یکی باشه، قبلا اینجوری می نوشتیم:
class Meta:
unique_together = ('product', 'color')
توی UniqueConstraint اینجوریه:
class Meta:
constraints = [
models.UniqueConstraint(fields=['product', 'color'], name='unique_product_option')
]
تازه میتونیم بگیم در شرایطی خاص این حالت فعال باشه.
خودتون زحمت بکشید condition رو توی لینکی که دادم سرچ کنید.
قابلیت های دیگه ای هم داره، که بازم خودتون...
و من الله التوفیق
Django Project
Model Meta options | Django documentation
The web framework for perfectionists with deadlines.
❤10✍5👍3
اصل انیشتین: چرا حفظ کردن، مهارت نیست؟
روایت معروفی وجود دارد که از آلبرت انیشتین سرعت نور را پرسیدند و او در پاسخ گفت: «نمیدانم. چرا باید چیزی را حفظ کنم که میتوانم در عرض چند ثانیه در کتاب پیدا کنم؟»
این جمله، امروز بیش از هر زمان دیگری مصداق دارد. در دنیایی که پاسخ هر سوال فنی، از سینتکس یک تابع گمنام در جاوااسکریپت گرفته تا پیچیدهترین مفاهیم معماری نرمافزار، با یک جستجوی ساده در گوگل یا LLMها در دسترس است، چرا باید از یک برنامهنویس انتظار داشته باشیم که همهچیز را از حفظ باشد؟
یک توسعهدهنده خوب کسی نیست که تعریف دقیق حرف D در اصول SOLID (Dependency Inversion Principle) را طوطیوار تکرار کند. بلکه کسی است که میداند چنین اصولی وجود دارد، فلسفه پشت آن را درک کرده و مهمتر از همه، میداند در چه شرایطی و چگونه از آن برای حل یک مشکل واقعی در پروژه استفاده کند. او اگر جزئیات را فراموش کرده باشد، میداند کجا به دنبال آن بگردد. این همان مهارت واقعی است.
این رویکرد اغلب به دلایل زیر در مصاحبهها باب شده است:
سنجش آسان: پرسیدن سوالات تعریفی، راهی ساده برای «نمره دادن» و فیلتر کردن سریع کاندیداهاست. پاسخ یا درست است یا غلط و نیازی به تحلیل عمیق ندارد.
عدم آموزش مصاحبهکنندگان: بسیاری از مصاحبهکنندگان فنی، خودشان توسعهدهندگان ارشدی هستند که برای مصاحبه کردن آموزش ندیدهاند. آنها بهطور طبیعی سوالاتی را میپرسند که خودشان پاسخ قطعیاش را میدانند؛ یعنی تعاریف و الگوریتمهای مشخص.
رویکردی بهتر: چگونه استعداد واقعی را کشف کنیم؟
پیشنهاد میشود به جای آزمون حافظه، روی سنجش مهارتهای کلیدی و شبیهسازی محیط کار واقعی تمرکز کنیم:
۱. سوالات مبتنی بر «تجربه» بپرسید، نه «تعریف»
به جای اینکه بپرسید: «حرف D در SOLID چیست؟»
بپرسید: «میتوانی پروژهای را مثال بزنی که در آن از اصل Dependency Inversion استفاده کردی؟ چه مشکلی را برایت حل کرد و اگر استفاده نمیکردی چه اتفاقی میافتاد؟»
این سوال، درک عمیق و تجربه عملی فرد را نشان میدهد، نه توانایی حفظ کردن او را.
۲. مسائل واقعی و مشترک طراحی کنید
به جای دادن یک مسئله الگوریتمی پیچیده و درخواست حل آن روی وایتبورد بدون اینترنت، یک چالش کوچک و واقعی از پروژه فعلی شرکت را مطرح کنید.
بگویید: «بیا با هم این مشکل را حل کنیم. فرض کن این تسک به تو داده شده. میتوانی از اینترنت هم استفاده کنی و بلند بلند فکر کن تا من با روند تحلیلت آشنا شوم.»
این روش، توانایی جستجو، یادگیری، و مهمتر از همه، رویکرد او به حل مسئله را آشکار میکند که در کار روزمره هزاران بار ارزشمندتر از حفظ بودن یک الگوریتم است.
سخن پایانی: مغز را استخدام کنید، نه هارد دیسک را
هدف ما از استخدام، پیدا کردن یک مغز متفکر و حلکننده مسئله است، نه یک دایرةالمعارف متحرک.
✍🏻 sina khaghani
روایت معروفی وجود دارد که از آلبرت انیشتین سرعت نور را پرسیدند و او در پاسخ گفت: «نمیدانم. چرا باید چیزی را حفظ کنم که میتوانم در عرض چند ثانیه در کتاب پیدا کنم؟»
این جمله، امروز بیش از هر زمان دیگری مصداق دارد. در دنیایی که پاسخ هر سوال فنی، از سینتکس یک تابع گمنام در جاوااسکریپت گرفته تا پیچیدهترین مفاهیم معماری نرمافزار، با یک جستجوی ساده در گوگل یا LLMها در دسترس است، چرا باید از یک برنامهنویس انتظار داشته باشیم که همهچیز را از حفظ باشد؟
یک توسعهدهنده خوب کسی نیست که تعریف دقیق حرف D در اصول SOLID (Dependency Inversion Principle) را طوطیوار تکرار کند. بلکه کسی است که میداند چنین اصولی وجود دارد، فلسفه پشت آن را درک کرده و مهمتر از همه، میداند در چه شرایطی و چگونه از آن برای حل یک مشکل واقعی در پروژه استفاده کند. او اگر جزئیات را فراموش کرده باشد، میداند کجا به دنبال آن بگردد. این همان مهارت واقعی است.
این رویکرد اغلب به دلایل زیر در مصاحبهها باب شده است:
سنجش آسان: پرسیدن سوالات تعریفی، راهی ساده برای «نمره دادن» و فیلتر کردن سریع کاندیداهاست. پاسخ یا درست است یا غلط و نیازی به تحلیل عمیق ندارد.
عدم آموزش مصاحبهکنندگان: بسیاری از مصاحبهکنندگان فنی، خودشان توسعهدهندگان ارشدی هستند که برای مصاحبه کردن آموزش ندیدهاند. آنها بهطور طبیعی سوالاتی را میپرسند که خودشان پاسخ قطعیاش را میدانند؛ یعنی تعاریف و الگوریتمهای مشخص.
رویکردی بهتر: چگونه استعداد واقعی را کشف کنیم؟
پیشنهاد میشود به جای آزمون حافظه، روی سنجش مهارتهای کلیدی و شبیهسازی محیط کار واقعی تمرکز کنیم:
۱. سوالات مبتنی بر «تجربه» بپرسید، نه «تعریف»
به جای اینکه بپرسید: «حرف D در SOLID چیست؟»
بپرسید: «میتوانی پروژهای را مثال بزنی که در آن از اصل Dependency Inversion استفاده کردی؟ چه مشکلی را برایت حل کرد و اگر استفاده نمیکردی چه اتفاقی میافتاد؟»
این سوال، درک عمیق و تجربه عملی فرد را نشان میدهد، نه توانایی حفظ کردن او را.
۲. مسائل واقعی و مشترک طراحی کنید
به جای دادن یک مسئله الگوریتمی پیچیده و درخواست حل آن روی وایتبورد بدون اینترنت، یک چالش کوچک و واقعی از پروژه فعلی شرکت را مطرح کنید.
بگویید: «بیا با هم این مشکل را حل کنیم. فرض کن این تسک به تو داده شده. میتوانی از اینترنت هم استفاده کنی و بلند بلند فکر کن تا من با روند تحلیلت آشنا شوم.»
این روش، توانایی جستجو، یادگیری، و مهمتر از همه، رویکرد او به حل مسئله را آشکار میکند که در کار روزمره هزاران بار ارزشمندتر از حفظ بودن یک الگوریتم است.
سخن پایانی: مغز را استخدام کنید، نه هارد دیسک را
هدف ما از استخدام، پیدا کردن یک مغز متفکر و حلکننده مسئله است، نه یک دایرةالمعارف متحرک.
✍🏻 sina khaghani
👍26👏8❤3👎1