رابطهی ForeignKey
گفتیم که در مدلهای رابطهای دادهها، یکی از رایجترین انواع روابط، رابطه یک به چند (One-to-Many) که در جنگو با ForeignKeyField
تعریف میگردد و مدلی برای مدیریت پروژهها ایجاد کردیم که هر پروژه به یک کاربر (مالک) تعلق داشته باشد. ولی در عین حال، کاربران میتوانستند مالک چندین پروژه باشند.
class Project(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name="projects") # ManyToOne Field
...
✺✳ دسترسی معکوس (Reverse Access) ✳✺
با تعریف جنگو، ForeignKey
، بهصورت خودکار امکان دسترسی معکوس را فراهم میکند. یه عبارتی، علاوه بر اینکه از طربق پروژه میتوان به مالک آن دسترسی داشت، از کاربر نیز میتوان به لیست پروژههایش دسترسی پیدا کرد.
⮜ دریافت تمام پروژههای یک کاربر
owner = User.objects.get(id=1)
# Method 1: If related_name is not set (Django default)
projects = owner.project_set.all()
# Method 2: When related_name is set to "projects" (recommended)
projects = owner.projects.all()
⚠️ اگر در تعریف ForeignKey
از پارامتر related_name
استفاده نموده باشیم، نباید از نام پیشفرض (modelname_set
) استفاده کنیم. در غیر این صورت با خطای AttributeError
مواجه خواهیم شد.
⮜ دریافت مالک یک پروژه
projectObj = Project.objects.get(id="ac260bde5f1347449f239052420573a7")
owner = projectObj.owner
✺✳ فیلتر کردن بر اساس روابط (Lookups across relationships) ✳✺
جنگو اجازه میدهد تا با استفاده از دو زیرخط (__
)، دادهها را بر اساس فیلدهای مدلهای مرتبط جستجو نمود.
⮜ دریافت تمام پروژههای یک کاربر
projectObjs = Project.objects.filter(owner__username="admin")
⮜ دریافت تمام کاربرانی که حداقل یک پروژه در حوزه "ai" دارند
# Method 1: If related_name is not set (Django default)
userObjs = User.objects.filter(project__area__icontains="ai")
# Method 2: When related_name is set to "projects" (recommended)
users = User.objects.filter(projects__area__icontains="ai")
⚠️ project
نام مدل مرتبط است ( در صورت عدم تعریف پارامتر related_name
، جنگو بهصورت پیشفرض، از نام مدل به صورت کوچکشده استفاده میکند). اما اگر related_name="projects"
تعریف شده باشد، باید از آن استفاده کرد.