جنگولرن
3.83K subscribers
287 photos
75 videos
31 files
558 links
آموزش Django و بستگان
Download Telegram
سوال:
شما اسلایدر برای سایت تون چطوری می سازید؟

این پیشنهاد 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 محسوب میشه.
10👍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 بسازی:
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 دقیقاً به کدوم جدول اشاره می‌کنه).
8👍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

یه مثال:
فرض کن میخواهیم ترکیب محصول و رنگ فقط یکی باشه، قبلا اینجوری می نوشتیم:
class Meta:
unique_together = ('product', 'color')

توی UniqueConstraint اینجوریه:
class Meta:
constraints = [
models.UniqueConstraint(fields=['product', 'color'], name='unique_product_option')
]


تازه میتونیم بگیم در شرایطی خاص این حالت فعال باشه.
خودتون زحمت بکشید condition رو توی لینکی که دادم سرچ کنید.
قابلیت های دیگه ای هم داره، که بازم خودتون...

و من الله التوفیق
115👍3
اصل انیشتین: چرا حفظ کردن، مهارت نیست؟
روایت معروفی وجود دارد که از آلبرت انیشتین سرعت نور را پرسیدند و او در پاسخ گفت: «نمی‌دانم. چرا باید چیزی را حفظ کنم که می‌توانم در عرض چند ثانیه در کتاب پیدا کنم؟»

این جمله، امروز بیش از هر زمان دیگری مصداق دارد. در دنیایی که پاسخ هر سوال فنی، از سینتکس یک تابع گمنام در جاوااسکریپت گرفته تا پیچیده‌ترین مفاهیم معماری نرم‌افزار، با یک جستجوی ساده در گوگل یا LLMها در دسترس است، چرا باید از یک برنامه‌نویس انتظار داشته باشیم که همه‌چیز را از حفظ باشد؟

یک توسعه‌دهنده خوب کسی نیست که تعریف دقیق حرف D در اصول SOLID (Dependency Inversion Principle) را طوطی‌وار تکرار کند. بلکه کسی است که می‌داند چنین اصولی وجود دارد، فلسفه پشت آن را درک کرده و مهم‌تر از همه، می‌داند در چه شرایطی و چگونه از آن برای حل یک مشکل واقعی در پروژه استفاده کند. او اگر جزئیات را فراموش کرده باشد، می‌داند کجا به دنبال آن بگردد. این همان مهارت واقعی است.

این رویکرد اغلب به دلایل زیر در مصاحبه‌ها باب شده است:

سنجش آسان: پرسیدن سوالات تعریفی، راهی ساده برای «نمره دادن» و فیلتر کردن سریع کاندیداهاست. پاسخ یا درست است یا غلط و نیازی به تحلیل عمیق ندارد.

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

رویکردی بهتر: چگونه استعداد واقعی را کشف کنیم؟
پیشنهاد می‌شود به جای آزمون حافظه، روی سنجش مهارت‌های کلیدی و شبیه‌سازی محیط کار واقعی تمرکز کنیم:

۱. سوالات مبتنی بر «تجربه» بپرسید، نه «تعریف»
به جای اینکه بپرسید: «حرف D در SOLID چیست؟»
بپرسید: «می‌توانی پروژه‌ای را مثال بزنی که در آن از اصل Dependency Inversion استفاده کردی؟ چه مشکلی را برایت حل کرد و اگر استفاده نمی‌کردی چه اتفاقی می‌افتاد؟»

این سوال، درک عمیق و تجربه عملی فرد را نشان می‌دهد، نه توانایی حفظ کردن او را.

۲. مسائل واقعی و مشترک طراحی کنید
به جای دادن یک مسئله الگوریتمی پیچیده و درخواست حل آن روی وایت‌بورد بدون اینترنت، یک چالش کوچک و واقعی از پروژه فعلی شرکت را مطرح کنید.
بگویید: «بیا با هم این مشکل را حل کنیم. فرض کن این تسک به تو داده شده. می‌توانی از اینترنت هم استفاده کنی و بلند بلند فکر کن تا من با روند تحلیلت آشنا شوم.»

این روش، توانایی جستجو، یادگیری، و مهم‌تر از همه، رویکرد او به حل مسئله را آشکار می‌کند که در کار روزمره هزاران بار ارزشمندتر از حفظ بودن یک الگوریتم است.

سخن پایانی: مغز را استخدام کنید، نه هارد دیسک را
هدف ما از استخدام، پیدا کردن یک مغز متفکر و حل‌کننده مسئله است، نه یک دایرةالمعارف متحرک.

✍🏻 sina khaghani
👍34👏94👎1
وات ایز F() expressions در جنگو 😁

جنگو در مورد تابع F توی داکیومنت میگه:

An F() object represents the value of a model field, transformed value of a model field, or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.
Django uses the F() object to generate an SQL expression that describes the required operation at the database level.

آخرش چی گفته؟ database level

این تابع برای مواقعی به درد میخوره که ممکنه همزمانی یا Concurrency پیش بیاد.
مثلا یه جایی میخواییم از انبار یه محصول کم کنیم، همزمان یه ریکوئست دیگه میاد که اونم میخواد کم کنه.
حالت عادی و بدون استفاده از F ، چون آبجکت توی مموری اومده و مثلا مقدار انبار 10 هست، هر دو از آبجکت توی مموری کم میکنن،
لذا انبار 9 میشه 😳
ولی با F مستقیم آپدیت روی رکورد زده میشه.

پیچوندمش؟ 😅 یه مثال:

فرض کن یه مدل داریم:
class Product(models.Model):
name = models.CharField(max_length=100)
stock = models.IntegerField(default=0)

حالا بخوایم یه محصول رو یه دونه کم کنیم:
product = Product.objects.get(id=1)
product.stock = product.stock - 1
product.save()

مشکل:
اگر دو درخواست هم‌زمان این کار رو بکنن، ممکنه هر دو یک مقدار قدیمی بخونن (مثلاً stock=10) و بعد از save، نتیجه بشه stock=9، در حالی که باید 8 می‌شد!
این همون مشکل همزمانی (Concurrency ) هست.

با F اینجوری میشه:
from django.db.models import F

Product.objects.filter(id=1).update(stock=F('stock') - 1)

اینجا F('stock') به دیتابیس می‌گه:
«به جای اینکه مقدار stock رو بیارم تو پایتون و دوباره بنویسم، مستقیماً در سطح دیتابیس مقدار فیلد رو یکی کم کن.»

این کار باعث می‌شه اتمیک (atomic) باشه و نیازی به lock دستی یا نگرانی از race condition نباشه.

راستی این lock باعث Deadlock نمیشه.
چون Deadlock وقتی پیش میاد که دو یا چند تراکنش هم‌زمان قفل منابع مختلف رو بگیرن و هرکدوم منتظر آزاد شدن قفل اونوری بمونن.
👍157🆒41
Forwarded from نمای پشت صحنه
توی سیستم های توزیع شده همون‌طور که میدونید ما یه چیزی داریم به اسم load balancer که میاد جلوی سرورا قرار میگیره و  request هایی که میان رو بین سرورا پخش می‌کنه. حالا چجوری و با چه منطقی پخش میکنه؟

اینا مرسوم ترین روش ها هستن حالا بسته به وضعیت میشه هر کدوم یا ترکیبی ازشون رو انتخاب کرد:

1️⃣ Round Robin
درخواست‌ها یکی‌ یکی و به ترتیب بین سرورها تقسیم میشن. ساده و رایج هست، ولی توان سرورها رو در نظر نمی‌گیره.

2️⃣ Weighted Round Robin
همون Round Robin ولی سرورهای قوی‌تر درخواست‌ های بیشتری می‌گیرن. اینطوری فشار متعادل‌ تر پخش میشه.

3️⃣ Least Connections
هر درخواست جدید به سروری میره که کمترین Connection فعال رو داره. برای کارهایی که زمان پردازش متغیر دارن خیلی خوبه.

4️⃣ IP Hash
این روش میاد IP کاربر رو هش می‌کنه و توی رنج تعداد سرور ها میزاره مثلا۱۰ تا سرور داریم میشه ۱ تا ۱۰ و request های یک IP همیشه به یه سرور میرن . این روش برای Session ها یا وب‌ اپلیکیشن‌ هایی که state دارن مفیده.

5️⃣ Least Response Time
درخواست‌ها به سمتی میرن که هم تعداد Connection کمتر باشه و هم response time سریع‌ تر. مناسب برای سرویس‌های حساس به Performance.
👍127
درمورد Descriptor چی می دونیم؟

چطوری می‌توان رفتارهای ویژگی‌های مرتبط به یک کلاس را مدیریت کرد؟ چطوری می‌توانیم کاری کنیم که ویژگی‌های متفاوت کلاس‌های مختلف به شکلی یکسان مدیریت شوند؟

ما در حالت ساده هیچ کنترلی روی ویژگی (Attribute) هایی که یک کلاس دارد نداریم.
وقتی شما کلاسی دارید که یک ویژگی به نام x دارد، هنگام کار با نمونه‌های ساخته‌شده از این کلاس می‌توان هر مقداری را به این ویژگی نسبت داد.
مثلاً فرض‌کنید که ما یک کلاس به نام Person داریم که مقدار سن شخص در آن نگهداری می‌شود:
class Person:
def __init__(self, age):
self.age = age

حالا ما موقع ساخت یک نمونه از این کلاس می‌توانیم «هرچیزی» را به آن نسبت بدهیم:
person1 = Person(10000)
person2 = Person(-10)
person3 = Person("I am not even an integer!")

در حالت ساده ما هیچ کنترلی روی ویژگی‌ها نداریم. پس تمام نمونه‌های بالا از نظر زبان پایتون درست هستند. امّا این مقادیر منطق برنامه‌ی ما را خراب می‌کنند.

شما می‌توانید برای اعتبارسنجی (Validation) مقادیر کدهای اضافی‌ای را درون init قرار بدهید. امّا آن کدها دیگر تغییرات مقادیر را پس از ساخت شئ کنترل نمی‌کنند.

حتّی می‌توانید متدهایی برای اعتبارسنجی درون کلاس‌تان بگذارید. امّا این کار تنها استفاده از کدتان را برای دیگران سخت‌تر می‌کند و همواره این احتمال وجود دارد که برنامه‌نویس فراموش کند که پس از هرتغییری در هر جای کد، آن متدها را فراخوانی کند.

از این مورد بگذریم.

فرض‌کنید که شما می‌خواهید یک ویژگی درون کلاس A همیشه عدد مثبت باشد. حالا در جای دیگر برنامه نیازدارید که چند ویژگی کلاس B هم درست همین خاصیّت را داشته باشند.
کلاس‌های A و B هم هیچ ربط منطقی‌ای ندارند و نمی‌توان به مواردی مثل ارث‌بری حتّی فکر کرد.
عالی نبود اگر می‌شد کاری کرد که ویژگی‌های کلاس های مختلف، بدون اینکه به هم ربطی پیدا کنند، به یک شکل مدیریت شوند؟

خب Descriptor پروتکلی است که همه‌ی این کارها را برای ما می‌کند.
پروتکل Descriptor خیلی ساده است. هر کلاسی که حداقل یکی از متدهای: set، get یا delete را پیاده‌سازی کند یک Descriptor حساب می‌شود.

کاربردها و مثال های Descriptor رو خودتون بخونید.
از سایت علی حسینی کپی کردم. این لینک

میخوام یه قابلیت ساده که توی جنگو هست رو توضیح بدم.
اما قبلش اگه بدونیم Descriptor چیه، یادگرفتنش باحال تر میشه.
پس اگه عمری بود، بقیه در پست های بعدی...


اسپانسر این قسمت 👈 لینک
👏62👍2
جنگولرن
وات ایز F() expressions در جنگو 😁 جنگو در مورد تابع F توی داکیومنت میگه: An F() object represents the value of a model field, transformed value of a model field, or annotated column. It makes it possible to refer to model field values and perform database…
نکته ای از عثمان در مورد پست F

ی مورد دیگه که خود جنگو داره از F object استفاده میکنه زمانیه که شما سعی میکنی ی رکورد جدید توی تیبل ایجاد کنی که اگه همون موقع بدون کال کردن refresh_from_db بیای یکی از فیلدهای رکورد جدید رو تو ی کوئری یا ایجاد رکورد تو ی جدول دیگه استفاده کنی توی کوئری یا ترنزکشنت ORM میاد دقیقا به اسم همون فیلد ترجمه میکنه، مثال:

شما فکر کنید ی تیبل به اسم Stock دارید و ی تیبل دیگه به اسم StockLog
فیلدهای استاک:
quantity
quantity_allocated

فیلدهای استاک لاگ:
initial_quantity
final_quantity

حالا شما ی رکورد جدید تو تیبل استاک می سازید:
stock = Stock.objects.create(quantity=10, quantity_allocated=0)

و میای بعدش میگی:
StockLog.objects.create(initial_quantity=0, final_quantity=stock.quantity)

Orm -> insert into stocklog(initial_quantity, quantity) values(0, 10)

اینجا حتما باید حواست به رفرش قبل اساین باشه
5🤔41
چرا ذهن ما عاشق Abstraction زودهنگام است؟

خیلی وقت‌ها در تیم‌های نرم‌افزاری می‌بینیم که مهندسان خیلی زود به سراغ abstraction و generalization می‌روند. یعنی قبل از اینکه حتی نیاز واقعی شکل بگیرد، یک لایه انتزاعی طراحی می‌کنند تا برای آینده آماده باشند.

این رفتار بی‌دلیل نیست. ذهن ما از نظر تکاملی عادت دارد الگوها را سریع تشخیص دهد و تعمیم دهد. همین باعث شده است که حتی وقتی دو سناریوی مشابه می‌بینیم، ناخودآگاه به فکر ساختن یک راه‌حل عمومی می‌افتیم. در زندگی روزمره این توانایی به بقای ما کمک کرده، اما در دنیای نرم‌افزار همیشه مفید نیست.

مشکل اصلی اینجاست که وقتی زود abstraction بسازیم، سطح اشتباه را انتخاب می‌کنیم. نه آنقدر بالا که به درد بخورد، نه آنقدر دقیق که واقعاً نیاز را برطرف کند. نتیجه این می‌شود که کدی می‌نویسیم که پیچیده‌تر از چیزی است که لازم داریم، و سرعت یادگیری و تغییر را پایین می‌آورد.

در عین حال، فرهنگ و فضای آموزشی هم این عادت را تقویت می‌کند. همه جا به ما گفته‌اند تکرار بد است یا باید برای reuse طراحی کنی. در حالی‌ که در بسیاری از موقعیت‌ها بهترین کار این است که ابتدا با ساده‌ترین راه‌حل شروع کنیم و بعد، وقتی چند بار نیاز تکرار شد و الگو روشن شد، سراغ abstraction برویم.

به جای پیش‌بینی آینده، باید برای تغییر آماده باشیم. به جای اینکه یک معماری عمومی از روز اول طراحی کنیم، بهتر است ساختار را طوری بچینیم که refactor راحت باشد. یعنی اول مسأله را حل کنیم، بعد اگر دیدیم الگو دارد تکرار می‌شود، abstraction را بسازیم.

آیا ما واقعاً می‌خواهیم برای آینده‌ای که هنوز نیامده هزینه بدهیم؟ یا می‌خواهیم امروز ساده شروع کنیم و اجازه بدهیم کد و معماری با واقعیت رشد کند؟

✍🏻 Kayvan Alimohammadi
65👍3
This media is not supported in your browser
VIEW IN TELEGRAM
یکی از دانش آموزام اینو برام فرستاده
.
.
.
من معلم هنرستان کامپیوترم 😬
.
.
.
قبول شد
البته هنرستان باید 12 بگیرن که قبول بشن
😁24
آیا می دانستید که وقتی ImageField یا FileField توی جنگو دارید، و اون رکورد حذف میشه، فایل هاش حذف نمیشن

درسته؟ قبول داری؟

تا جایی که من میدونم فایل ها حذف نمیشن
یا مثلا عکس رو تغییر بدیم، عکس قبلی ع توی سرور میمونه
در واقع media حذف نمیشه

راه حل چیه؟

چند تا راه هست:

-متد save و delete رو override کن و دستی حذف کن.
-از سیگنال های جنگو استفاده کن و رکورد حذف شد، سیگنال فایل هارو حذف کنه.
-استفاده از پکیج django-cleanup که دقیقا کارش همینه، و از سیگنال ها استفاده میکنه.
-استفاده از پکیج django-lifecycle که کارش حذف کردن فایل نیست، ولی با قابلیت hook ش میشه فایل های بی صاحب رو حذف کرد 😁

پکیج django-lifecycle برای من جالب بود
مدل مون باید از LifecycleModel ش ارث بری کنه
بعد یه سری Hook داره و میگه بعد از فلان اتفاق، فلان کار رو انجام بده
نمیاد سیگنال کال کنه، متد save و delete رو override کرده.

من باشم از هر دوشون همزمان استفاده میکنم.
با تشکر از Hossein Neysian
نظری اگه دارید بگید. مثلا ابزار یا پکیجی که برای این موارد استفاده میشه.
یا توی پروژه های Enterprise اینو چطور هندل میکنن، اصلا این مسئله هست توی پروژه های Enterprise ؟؟؟

اسپانسر این پست 👈 لینک
3