وراثت به شما امکان می دهد از کدها مجددا استفاده کنید و مدل های داده تمیزتر ایجاد کنید. اما جنگو بیش از یک راه برای ارث بردن ارائه می دهد، بنابراین مطمئن شوید که تفاوت ها را می دانید.
وراثت مدل یک ویژگی ORM جنگو است که به توسعه دهندگان اجازه می دهد تا روابط سلسله مراتبی بین مدل های پایگاه داده ایجاد کنند. با استفاده از اصول برنامه نویسی شی گرا، استفاده مجدد از کد، توسعه پذیری و یک پایه کد تمیزتر را امکان پذیر می کند.
چه در حال ساخت یک برنامه وب پیچیده یا کار بر روی یک پروژه کوچکتر باشید، وراثت مدل می تواند مزایای قابل توجهی مانند کاهش افزونگی و اطمینان از رفتار ثابت ارائه دهد.
انواع وراثت مدل در جنگو
جنگو از سه نوع وراثت مدل پشتیبانی می کند:
- کلاس های پایه چکیده.
- ارث بری چند جدولی
- مدل های پروکسی
هر یک از این نوع ارث بری مدل دارای مزایایی است و شما از آنها برای اهداف خاصی استفاده خواهید کرد.
کلاس های پایه چکیده
کلاسهای پایه انتزاعی راهی برای تعریف فیلدها و روشهای مشترکی ارائه میکنند که چندین مدل میتوانند به ارث ببرند. به عنوان مثال، اگر دو مدل دارید که فیلدهای مشابه را به اشتراک می گذارند، می توانید از یک کلاس پایه انتزاعی برای تعریف فیلدهای مشابه استفاده کنید. به این مثال توجه کنید:
class Customer(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
customer_id = models.IntegerField()
class Seller(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
seller_id = models.IntegerField()
قطعه کد بالا دو مدل جنگو را تعریف می کند: مشتری و فروشنده. این مدل ها دو فیلد مشترک یعنی نام و ایمیل دارند. برای جلوگیری از این افزونگی، می توانید یک مدل جداگانه ایجاد کنید تا فیلدهای مشترک در مدل های مشتری و فروشنده را نگه دارید و آن را انتزاعی کنید.
class UserInfo(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
class Meta:
abstract = True
قطعه کد بالا یک مدل جدید را تعریف می کند و ویژگی abstract را روی True قرار می دهد. این بدان معناست که مدل انتزاعی خواهد بود و جنگو جدولی در پایگاه داده ایجاد نخواهد کرد.
می توانید مدل های مشتری و فروشنده را به صورت زیر بازنویسی کنید:
class Customer(UserInfo):
customer_id = models.IntegerField()
class Seller(UserInfo):
seller_id = models.IntegerField()
در قطعه کد بالا، مدل های Customer و Sellers به جای models.Model از مدل UserInfo ارث می برند.
شما می توانید مدل های خود را در پنل مدیریت با ثبت آنها در فایل admin.py به صورت زیر مشاهده کنید:
from .models import Customer, Seller
admin.site.register(Customer)
admin.site.register(Seller)
حالت های خود را مهاجرت کنید و سرور توسعه خود را با اجرای موارد زیر در خط فرمان راه اندازی کنید:
python manage.py makemigrations \
&& python manage.py migrate \
&& python manage.py runserver
به سایت مدیریت خود بروید و با جزئیات سوپرکاربر خود وارد شوید. شما باید هر سه فیلد را برای هر مدل ببینید.
در این مثال، جنگو یک جدول برای مدل های مشتری و فروشنده ایجاد کرده است. می بینید که مدل UserInfo از آنجایی که انتزاعی است هیچ جدولی ندارد.
ارث بری چند جدولی
زمانی که مدل والد نیز باید به عنوان جدول در پایگاه داده در کنار مدل فرزند وجود داشته باشد، می توانید از ارث بری چند جدولی استفاده کنید.
بر خلاف وراثت کلاس پایه انتزاعی، که در آن مدل والد یک جدول در پایگاه داده نخواهد بود، وراثت چند جدولی یک جدول برای مدل والد ایجاد می کند.
در وراثت چند جدولی، مدل فرزند تمام فیلدها و متدها را از مدل والد خود به ارث برده و فیلدهای خاص خود را اضافه می کند. کلیدهای خارجی به ایجاد رابطه مدل بین مدل های والدین و فرزند کمک می کنند.
در اینجا یک مثال از ارث بری چند جدول آورده شده است:
class Person(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
def get_name(self):
return f"{self.first_name} {self.last_name}"
class Meta:
abstract = True
class Employee(Person):
employee_id = models.CharField(max_length=20)
department = models.CharField(max_length=100)
salary = models.FloatField()
dob = models.DateField()
class Manager(Employee):
title = models.CharField(max_length=100)
این قطعه کد سه مدل را تعریف می کند. مدل اول که Person نام دارد، انتزاعی است. فقط نام و نام خانوادگی افراد را مشخص می کند.
مدل دوم که Employee نام دارد، فیلدهای Person را به ارث می برد اما فیلدهای اضافی را تعریف می کند. مدل Employee انتزاعی نیست، بنابراین جدول خود را در پایگاه داده خواهد داشت.
مدل نهایی که Manager نام دارد، فیلدهای مدل Employee را به ارث می برد و فیلدی به نام عنوان اضافه می کند.
رابطه بین مدل های کارمند و مدیر، ارث بری چند جدولی نامیده می شود. مدل های خود را مهاجرت کنید، آنها را در admin.py ثبت کنید، سرور خود را راه اندازی کنید و به پنل مدیریت بروید. شما باید دو جدول ایجاد شده توسط جنگو را ببینید.
وقتی میخواهید مدیر جدیدی اضافه کنید، متوجه میشوید که تمام فیلدهای مدل Employee و همچنین فیلد سفارشی خود را دارد.
مدل های پروکسی
یک مدل پراکسی به شما کمک می کند یک مدل جدید ایجاد کنید که از مدل موجود بدون ایجاد جدول پایگاه داده جدید گسترش یابد. در این نوع وراثت مدل، مدل های پراکسی و اصلی یک جدول مشترک خواهند داشت. با استفاده از مدلهای پراکسی، میتوانید کارهایی مانند ایجاد مدلهای سفارشی و تغییر مدیران پیشفرض را انجام دهید.
می توانید با افزودن proxy=True در کلاس Meta یک مدل پراکسی ایجاد کنید. در اینجا یک مثال است:
class ProxyModel(BaseModel):
class Meta:
proxy = True
استفاده معمولی از یک مدل پراکسی زمانی مناسب است که یک مدل پایه وجود داشته باشد و نیاز به ایجاد یک نسخه تخصصی از آن با قابلیتهای اضافی وجود داشته باشد. در اینجا یک مثال اساسی آورده شده است:
class Post(models.Model):
title = models.CharField(max_length=30)
author = models.CharField(max_length=30)
def __str__(self):
return self.title
class ProxyPost(Post):
class Meta:
proxy = True
این قطعه کد دو مدل را تعریف می کند: Post و MyPost. مدل Post دو فیلد برای عنوان و نویسنده تعریف می کند. مدل ProxyPost از مدل Post ارث می برد.
مدل های بالا را مهاجرت کنید و یک پست جدید به جدول ایجاد شده برای مدل Post اضافه کنید.
پس از افزودن پست، جدول پست های پروکسی را باز کنید. شما باید پستی را که به جدول Post اضافه کرده اید در آن پیدا کنید.
تغییراتی که در پستهای جدول پستهای پروکسی ایجاد میکنید، روی پست مربوطه در جدول پست تأثیر میگذارد و بالعکس. این ثابت می کند که آنها واقعاً یک جدول مشترک دارند.
می توانید متد str() مدل پروکسی را تغییر دهید:
class ProxyPost(Post):
class Meta:
proxy = True
ordering = ["title"]
def __str__(self):
return self.author
با این اصلاح، نمایش رشته ProxyPost نویسنده آن خواهد بود، نه عنوان. ترتیب مدل پروکسی نیز به جای فیلد شناسه پیش فرض، بر اساس عنوان خواهد بود.
هنگام استفاده از مدل های پراکسی، باید به خاطر داشته باشید که نمی توانید فیلدهای سفارشی را به مدل پروکسی خود اضافه کنید. مورد استفاده اولیه از مدل های پراکسی زمانی است که می خواهید یک مدل از چندین رفتار پشتیبانی کند.
مدلهای پراکسی به شما کمک میکنند تا رفتار یک مدل موجود را بدون تغییر فیلدهای آن یا ساختار جدول پایگاه داده، تغییر دهید.
از وراثت مدل برای قابلیت استفاده مجدد کد و ساختار سازمانی استفاده کنید
با استفاده از تکنیک های مختلف وراثت مدل، می توانید به راحتی کد قابل استفاده مجدد و سازماندهی شده برای پروژه خود ایجاد کنید.
وراثت مدل از کد اضافی جلوگیری می کند و قابلیت نگهداری و مقیاس پذیری کد شما را افزایش می دهد. همچنین پیمایش کد شما را آسان می کند، بنابراین همکاری کارآمد بین تیم های توسعه را تقویت می کند.
جدا از وراثت مدل، جنگو وراثت قالب را ارائه می دهد که راهی عالی برای مدیریت و سازماندهی قالب ها برای پروژه های شما است.