آموزش جنگو (Basic) : جلسه بیست و یک | ارث بری مدل ها

در این جلسه به بررسی ارث بری کلاس مدل ها و انواع آن در جنگو خواهیم پرداخت . با ما همراه باشید . آموزش جنگو : جلسه بیست و یک | ارث بری مدل هامدل ها :ارث بری مدل هاوراثت در مدل های جنگو به همان شیوه که وراثت در پایتون کار میکند , کار میکنند . ولی اصل اولیه در جنگو باید رعایت شود . این یعنی باید کلاس مادر یا کلاس پایه شما از dajngo.db.models.Model ارث بری کند .تنها تصمیمی که باید بگیرید این است که آیا می خواهید کلاس والد به تنهایی خودشان یک مدل و جدول دیتابیس را تشکیل بدهند یا کلاس های والد فقط دارندگان اطلاعات مشترکی هستند که در کلاس فرزند وجود دارد و در آنها قابل مشاهده است .سه نوع از ارث بری ها در جنگو مجاز است :1-گاهی فقط می خواهید کلاس والد شامل اطلاعاتی باشد که نمی خواهید در هر کلاس فرزند آنها را دوباره بنویسید . این کلاس هرگز به صورت مجزا استفاده نمی شود و همیشه با کلاس های فرزند خود وارد محیط کار می شود . این نوع از ارث بری را Abstract میگویند .2-اگر یک مدل موجود را می خواهید از یک برنامه دیگر به صورت کامل طبقه بندی گنید و هر مدل جدول خود را در دیتابیس داشته باشد . در این هنگام استفاده از وراثت چندجدولی راه حل ما است. (در ادامه مثال آن را خواهید دید)3-در آخر ,اگر می خواهید بدون اینکه فیلد ها را تغییر دهید ,رفتاری از کلاس پایتون را در مدلی وارد کنید , باید از Proxy model استفاده کنید .استفاده از models Abstract baseاین نوع از ارث بری در مدل های جنگو معمولا بیشتر استفاده می شود . در این نوع اطلاعات رایج را در کلاس والد قرار می دهیم و در گلاس های فرزند آنها را استفاده میکنیم . شما کلاس والد را مینویسید و abstract را برابر با True قرار می دهید (در کلاس متا کد abstract=True را قرار می دهیم) . سپس بجای اینکه از کلاس والد برای ایجاد جدول دیتابیس استفاده شود ,در عوض به عنوان یک کلاس پایه و والد برای دیگر مدل ها استفاده می شود . وقتی اینکار انجام شود ,فیلد های کلاس والد به کلاس های فرزند منتقل می شوند .به مثال زیر نگاه کنید :from django.db import models class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField() class Meta: abstract = True class Student(CommonInfo): home_group = models.CharField(max_length=5)در مثال بالا,مدل Student شامل سه فیلد name , age , home_group خواهد بود . دو فیلد name و age از کلاس والد به آن ارث رسیده اند و فیلد بعدی در خود مدل Student ایجاد شده است . مدل اصلی و والد یا base نمیتواند به صورت مستقیم استفاده شود و فقط میتواند به عنوان کلاس والد برای مدل های دیگر عمل کند . دلیل آن این است که با abstract=True جنگو برای آن کلاس ,جدولی در دیتابیس نمی سازد و کلاس را به عنوان یک مدل نمی شناسد . (کلاس manager نخواهد داشت و غیرقابل استفاده به صورت مستقیم خواهد بود)فیلد های به ارث رسیده از کلاس والد را میتوان با مساوی قرار دادن با None حذف نمود و یا نوع فیلد جدیدی را به آنها مقدار دهی کرد (بازنویسی کرد).به طور خلاصه می توان گفت این روش بهترین روش ارث بری مدل هاست . در این روش اطلاعات مشترک میان چند مدل فاکتورگیری می شوند و در کلاس والد قرار می گیرند . در حالی که کلاس والد جدولی ندارد و هر کلاس فرزند یک جدول برای خود اختصاص می دهد .مدل ها : ارث بری در Meta classهنگامی که یک کلاس abstract class ایجاد می شود , جنگو هر کلاس Meta را که در کلاس والد یا اصلی تعریف کرده اید را به عنوان یک ویژگی یا attribute در دسترس قرار می دهد . اگر یک کلاس فرزند کلاس Meta خود را نداشته باشد ,آن را از والد خود به ارث می برد و این به این معنی است که تمام ویژگی های آن را کپی می کند . اگر کلاس فرزند بخواهد Meta را بازنویسی کند یا گسترش دهد باید آن را به صورت یک زیر کلاس از کلاس Meta والد تعریف کند . به مثال زیر نگاه کنید :from django.db import models class CommonInfo(models.Model): # ... class Meta: abstract = True ordering = ['name'] class Student(CommonInfo): # ... class Meta(CommonInfo.Meta): db_table = 'student_info'جنگو قبل از اینکه کلاس Meta را به ارث برساند ,تنظیماتی را روی کلاس و زیر کلاس های آن انجام می دهد . برای کلاس اصلی و والد abstract=False تنظیم خواهد شد و این بدان معناست که کلاس های فرزند به طور خودکار تبدیل به کلاس abstarct نخواهند شد . به طور خلاصه می توان گفت که اگر بخواهید کلاس فرزند نیز یک کلاس abstract class باشد یا کلاس فرزندی که از یک abstract base class ارث بری می کند خودش یک کلاس abstract بشود ,باید در گزینه های Meta فرزند به طور واضح و صریح abstract=True را قرار بدهید .برخی از ویژگی هایی که درون یک Meta کلاس تعریف میکنید ,برای ارث بری مناسب نیستند . بر فرض مثال در کلاس والد شما در زیر کلاس Meta آن , db_table را تعریف کرده اید . اگر این ویژگی به فرزندان ارث برسد , باعث می شود نام تمامی جدول ها در دیتابیس یکسان باشد و این مشکلاتی را برای شما ایجاد خواهد کرد .نکته :کلاس Meta والد در صورتی در فرزندان به ارث می رسد که برای کلاس فرزند کلاس Metaبازنویسی نشده باشد .همچنین اگر بخواهید مفهوم چند وراثتی را برای کلاس های Meta تعریف کنید ,باید به صراحت در زیر کلاس Meta کلاس هایی که از آنها ارث بری میکنید را ذکر کنید . به مثال زیر نگاه کنید :from django.db import models class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField() class Meta: abstract = True ordering =['name'] class Unmanaged(models.Model): class Meta: abstract = True managed = False class Student(CommonInfo, Unmanaged): home_group = models.CharField(max_length=5) class Meta(CommonInfo.Meta, Unmanaged.Meta): passاگر این کار را انجام ندهید ,خود پایتون به صورت پیش فرض اولین کلاس معرفی شده را پیدا میکند و اطلاعات Meta آن را به ارث می برد .مدل ها :مراقب related_name و related_query_name باشید!هرگاه شما از related_name و یا related_query_name در فیلد های ManytoMany یا Foriegnkey استفاده کنید ,شما در واقع نام معکوس یا reverse_name را به فیلد مورد نظر داده اید . (اگر با related_name ها آشنایی ندارید ,درباره آنها اطلاعاتی کسب کنید) دادن ویژگی related_name به یک فیلد در کلاسی که abstract=True باشد ,باعث مشکلاتی خواهد شد . زیرا فیلد هایی که در این کلاس یا همان کلاس والد وجود دارند در کلاس فرزندان به ارث خواهند رسید . این باعث ایجاد تداخل در دیتابیس شما خواهد شد زیرا شما نمی توانید دو فیلد با related_name های یکسان داشته باشید . (دو فرزند هر دو ,یک فیلد را با ویژگی های یکسان به ارث خواهند برد)برای حل این مشکل، وقتی از related_name یا related_query_name در یک کلاس والد یا abstract (فقط) استفاده می‌کنید، بخشی از مقدار باید حاوی %(app_label)s یا %(class)s باشد .با سینتکس %(class)s :در این بخش بجای کلمه class باید نام کلاس فرزندی که فیلد در آن مورد استفاده قرار می گیرد , قرار بگیرد .(با حروف کوچک باشد)با سینتکس %(app_label)s :این مقدار باید با نام اپ دربردارنده کلاس فرزند شما جایگزین شود . (نام باید با حروف کوچک باشد) هر اپ نام منحصر به فرد خود را دارد و همینطور هر کلاس نام منحصر به فردی دارد . پس نام حاصل متفاوت خواهد بود .برای مثال در common/models.pyکه نام اپ آن common است :from django.db import models class Base(models.Model): m2m = models.ManyToManyField( OtherModel, related_name=&quot%(app_label)s_%(class)s_related&quot, related_query_name=&quot%(app_label)s_%(class)ss&quot, ) class Meta: abstract = True class ChildA(Base): pass class ChildB(Base): passهمچنین در اپ rare و فایل rare/models.py داریم :from common.models import Base class ChildB(Base): passنام معکوس یا reverse name برای فیلد manytomany در ChildA برابر با common_childa_related خواهد بود که ابتدا نام اپ و سپس نام کلاس مرتبط و در اخر کلمه related است . همچنین برای فیلد manytomany به ارث رسیده برای ChildB این مقدار برابر با common_childb_related خواهد بود . در ChildB مقدار reverse query name بابر با common_childbs است که فرمول آن در کلاس والد قابل مشاهده است و نیازی به توضیح ندارد .در نهایت در اپ rare و کلاس ChildB مقدار متغییر reverse name برابر با rare_ChildB_related و مقدار متغییر reverse query name برای آن برابر با rare_childbs خواهد بود . این ها مقدار هایی هستند که بعدا در view برای کار با دیتابیس به کار خواهند رفت . (گرچه مقوله ارث بری کاربرد چندانی ندارد )گرچه اگر در کلاس والد شما مقدار related_name را تعریف نکنید ,مقدار پیش فرض آن به صورت نام کلاس فرزند به علاوه کلمه set_ خواهد بود . برای مثال در کد بالا اگر مقدار related name در کلاس والد یا Base را حذف کنیم ,مقدار related name یا همان reverse name برای فیلد manytomany در کلاس ChildA برابر با childa_set و در کلاس ChildB برابر با childb_set خواهد بود .مدل ها : ارث بری چند جدولینوع دوم وراثتی که توسط موتور های دیتابیس جنگو پشتیبانی می شود ,زمانی است که هر مدل در سلسله مراتب به تنهایی یک مدل باشد و در دیتابیس جدول های خود را داشته باشد .این باعث می شود حتی کلاس والد نیز بتواند در دیتابیس جستجو کند و manager مربوط به خود را داشته باشد .در این نوع از رابطه ها وراثت بین مدل فرزند و والدین آن از طریق فیلد OnetoOneField که به صورت خودکار ایجاد شده است ,تشکیل می شود . به مثال زیر نگاه کنید .from django.db import models class Place(models.Model): name = models.CharField(max_length=50) address = models.CharField(max_length=80) class Restaurant(Place): serves_hot_dogs = models.BooleanField(default=False) serves_pizza = models.BooleanField(default=False)در این مثال همه فیلد های کلاس Place در کلاس Restaurant در دسترس خواهند بود . بنابراین هر دو امکان پذیر است :>>> Place.objects.filter(name=&quotBob's Cafe&quot) >>> Restaurant.objects.filter(name=&quotBob's Cafe&quot)همچنین گفتیم که رابطه onetoone به صورت اتوماتیک برای مدل شما تعریف می شود . در اینجا اگر شی ای از مدل Place در مدل Restaurant نیز وجود داشته باشد ,شما میتوانید با مقدار نام کلاس به صورت حروف کوچک به آن از مدل والد دسترسی پیدا کنید . برای مثال :>>> p = Place.objects.get(id=12) # If p is a Restaurant object, this will give the child class: >>> p.restaurant <Restaurant: ...>با این حال ,اگر p در مدل Restaurant وجود نداشت (یعنی از کلاس Restaurant ایجاد نشده بود و از کلاس Place آن را ایجاد کرده بودید) جنگو به شما خطای DoesnNotExist را نشان می داد .نکته :اگر بخواهید شی را از مدل Place بسازید (place.objects.create) مقوله بالا برای ایجاد خطا درست است ,ولی اگر شی از کلاس Restaurant ساخته می شد (Restaurant.objects.create) ,شما باید فیلد های مدل place را نیز بخاطر ارث بری از آن مدل ,اختصاص می دادید ;ولی شما ارور Object DoesNotExist را دریافت نمی کردید .فیلد OneToOne ایجاد شده به صورت اتوماتیک برای مثال های بالا به شکل زیر است که نمایش داده نمی شود:place_ptr = models.OneToOneField( Place, on_delete=models.CASCADE, parent_link=True, primary_key=True, )شما می توانید آن را با نوشتن دوباره آن به صورتی که parent_link = True باشد در مدل Restaurant بازنویسی کنید .مدل ها : ارث بری چند جدولی و کلاس Metaدر ارث بری چند جدولی ,منطقی نیست که یک کلاس فرزند از کلاس Meta والد خود بهره ببرد و ارث بری کند . همه گزینه هایی که در کلاس Meta والد وجود دارند ,قبلا روی آن اعمال شده اند و استفاده مجدد از آنها در کلاس فرزند منطقی نیست . به همین دلیل رفتار های کلاس Meta از والد به فرزند در این نوع از ارث بری مدل ها به ارث نمی رسد.گرچه چندین موقعیت وجود دارند که باعث می شوند کلاس فرزند رفتاری را از والد به ارث ببرد . برای مثال فرض کنید که کلاس فرزند ordering خود را مشخص نکرده باشد یا متد get_latest_by در آن تعریف نشده باشد .در مثال های بالا ,فرزند از والدین خود این گونه رفتار ها را به ارث می برد .اگر والد رفتار ordering سفارشی خود را دارد و شما نمی خواهید فرزند آن را به ارث ببرد کافی است تا آن را در کلاس فرزند بازنویسی کنید . (در مثال پایین خالی بودن متغییر به معنای ordering پیش فرض است)class ChildModel(ParentModel): # ... class Meta: # Remove parent's ordering effect ordering = []مدل ها : وراثت و روابط معکوساز آنجایی که وراثت چند جدولی از یک OneToOneField برای پیوند دادن فرزند و والدین استفاده می کند، می توان مانند مثال بالا از والد به فرزند دسترسی داشت . با این حال، این از نامی استفاده می‌کند که مقدار related_name پیش‌فرض برای روابط ForeignKey و ManyToManyField است. اگر آن نوع روابط را در یک زیر کلاس از مدل والد قرار می دهید، باید ویژگی related_name را در هر یک از این فیلدها مشخص کنید. اگر فراموش کنید، جنگو یک خطای اعتبار سنجی ایجاد می کند.برای مثال بیایید زیرکلاسی دیگر با یک ManyToManyField به مدل والد ایجاد کنیم :class Supplier(Place): customers = models.ManyToManyField(Place)اگر دستور migrate را اجرا کنید ,ارور زیر را دریافت خواهید کرد .Reverse query name for 'Supplier.customers' clashes with reverse query name for 'Supplier.place_ptr'. HINT: Add or change a related_name argument to the definition for 'Supplier.customers' or 'Supplier.place_ptr'.برای حل این مشکل کافی است به فیلد ManyToManyField یا OneToOneField یک related_name بدهید .class Supplier(Place): customers = models.ManyToManyField(Place , related_name=“provider”)مدل ها : تعیین کردن نام فیلد پیوند در ارث بری چندجدولیهمانطور که گفته شد ,جنگو به صورت اتوماتیک در کلاس فرزند یک OneToOneField را ایجاد می کند که کلاس فرزند را به هر والد که abstarct = True نداشته باشد ,پیوند می دهد . برای کنترل کردن نام فیلد OneToOneField ایجاد شده به صورت اتوماتیک ,کافیست آن را در کلاس فرزند خودتان ایجاد کنید .اینگونه می توانید نام آن را خودتان تعیین کنید . (به یاد داشته باشید که باید مانند مثال های قبلی parent_link = True قرار داده شود)مدل ها : ارث بری proxyدر هنگام ارث بری چند جدولی ,برای هر کلاس والد و فرزند یک جدول در دیتابیس ایجاد می شود . این رفتار معمولا مورد استفاده زیادی قرار می گیرد زیرا کلاس فرزند میتواند اطلاعات اضافی که در کلاس والد نباید قرار داشته باشند را در خود ذخیره کند . با این حال گاهی اوقات شما فقط می خواهید تا رفتار یک مدل را تغییر دهید . (منظور این است که متد جدیدی را به آن اضافه کنید یا manager پیش فرض آن را تغییر دهید)این همان چیزی است که ارث بری proxy برای آن ساخته شده است . ایجاد یک پروکسی برای مدل . شما می توانید اطلاعات را از مدل proxy اضافه کنید , حذف کنید یا اپدیت کنید و جنگو این کار را طوری انجام می دهد که گویی از مدل اصلی (مدل غیر پروکسی) استفاده شده است . تفاوت آن این است که میتوانید در مدل proxy رفتار های متفاوتی داشته باشید (برای مثال رفتار ordering را تغییر دهید) و تاثیری بر روی مدل اصلی یا اورجینال نداشته باشید .به طور خلاصه شما مدلی را ایجاد می کنید که صرفا فقط و فقط رفتار های آن با مدل یا کلاس والد متفاوت است.برای ساخت یک proxy باید یک مدل معمولی را تعریف کنید ولی در کلاس Meta آن proxy را برابر با True قرار دهید.فرض کنید می خواهید متدی را به کلاس Person اضافه کنید .from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) class MyPerson(Person): class Meta: proxy = True def do_something(self): # ... passکلاس MyPerson روی همان جدول دیتابیس که برای Person ایجاد شده است تاثیر میگذارد و هر شی جدید ایجاد شده از هر دو کلاس قابل دسترسی خواهند بود .>>> p = Person.objects.create(first_name=&quotfoobar&quot) >>> MyPerson.objects.get(first_name=&quotfoobar&quot) <MyPerson: foobar>شما همچنین از proxy می توانید برای تعریف یک ترتیب پیش فرض متفاوت در یک مدل استفاده کنید . ممکن است بخواهید برای مثال در مدل Person دو ترتیب ordering متفاوت را داشته باشید ,در آن صورت مدل proxy را ایجاد می کنید و در کلاس Meta آن می نویسید :class OrderedPerson(Person): class Meta: ordering = [&quotlast_name&quot] proxy = Trueاکنون query مدل Person نامرتب خواهد بود و در صورتی که از کلاس OrderedPerson استفاده کنید , queryهای شما بر اساس last_name مرتب خواهند شد . (معمولا از این روش استفاده نمی کنند)نکته :مدل های proxy مانند مدل های معمولی ویژگی های متا را به ارث می برند .مدل ها : بازگرداندن شی در مدل proxyتوجه داشته باشید که اشیا در مدل proxy (در اینجا MyPerson) در واقع اشیایی هستند که در مدل Person ساخته شده اند و هیچ راهی وجود ندارد که اشیا در MyPerson در حالی که در Person جستجو میکنید قرار بگیرند و نمایش داده شوند . مدل های proxy صرفا برای تعاریف متد و رفتار های جدید یک مدل در حالی که مدل اصلی هنوز وجود دارد , قرار داده شده اند .مدل ها :محدودیت های کلاس والد یا پایهیک مدل proxy باید فقط از یک کلاس که abstract نباشد ,ارث بری کند . در این نوع از ارث بری مدل ها ,شما نمی توانید از چندین کلاس ارث بری کنید ,زیرا مدل های proxy هیچ ارتباطی میان چند جدول دیتابیس شما نمی توانند ایجاد کنند . اما در شرایطی که مدل های والد abstarct باشند ,میتوانید از هر چند مدل که می خواهید ارث بری کنید .گرچه در این صورت مدل proxy نباید هیچ فیلدی درون خود تعریف کند (دلیل آن در بالا گفته شد) . همچنین ممکن است یک مدل proxy از چندین مدل proxy دیگر که آنها نیز یک کلاس والد (abstract نباشند) مشترک دارند ,ارث بری کند .مدل ها : manager مدل های نوع proxyاگر شما یک manager را برای مدل proxy خود تعریف نکنید ,به صورت پیش فرض manager والدین خود را به ارث خواهد برد . اما در صورت تعریف یک manager خاص برای مدل proxy ,مدل شما از آن استفاده خواهد کرد. این در صورتی است که در کلاس های والد manager همچنان همان قبلی خواهد بود و تاثیری بر روی آن نخواهد داشت .در ادامه مثال قبلی ,شما می توانید یک manager جدید را در کلاس MyPerson تعریف کنید که در هنگام اجرای یک query از آن استفاده کنید . (بعد ها با نوشتن یک manager آشنا خواهید شد! فعلا همین را از ما قبول کنید)نکته :در هنگام استفاده از کلاس MyPerson , manager نوشته شده فراخوانی خواهد شد و اگر از کلاس Person در view خود استفاده کنید , manager پیش فرض خود جنگو فراخوانی میشود زیرا شما manager جدیدی را برای کلاس Person تعریف نکرده اید . (این در حالی است که هر دوی آنها بر روی یک جدول از دیتابیس کار می کنند و اشیا در آنها یکی است )from django.db import models class NewManager(models.Manager): # ... pass class MyPerson(Person): objects = NewManager() class Meta: proxy = Trueاگر می خواهید یک manager جدید را بدون جایگزین کردن manager پیش فرض به مدل proxy خود اضافه کنید ,فقط کافی است تا از تکنیک های توضیح داده شده در جلوتر استفاده کنید . در این تکنیک شما یک کلاس abstarct ایجاد خواهید کرد و manager را درون آن تعریف میکنید . سپس بعد از کلاس والد آن را به ارث می برید . به مثال زیر نگاه کنید :# Create an abstract class for the new manager. class ExtraManagers(models.Model): secondary = NewManager() class Meta: abstract = True class MyPerson(Person, ExtraManagers): class Meta: proxy = Trueگرچه این روش به طور معمول استفاده نمی شود . (همچنین با manager کمی جلوتر آشنا خواهید شد)مدل ها :ارث بری چندگانه (multiple inheritance)در پایتون این قابلیت وجود دارد که کلاس شما بتواند از چند والد همزمان ارث بری کند . جنگو نیز با پایتون نوشته شده است و این قابلیت را در خود دارا است . شما می توانید یک مدل ایجاد کنید که از چندین والد ارث بری کند . گرچه قوانین عادی نوشتن کلاس ها در پایتون بر روی جنگو نیز اعمال خواهد شد . برای مثال قانون اولین نام خاص می گوید اگر شما در جنگو چندین مدل A , B , C داشته باشید که هر کدام کلاس Meta مخصوص به خود را دارند و مدل D از همه ی آنها ارث بری کند ,کلاس Meta از مدلی به ارث خواهد رسید که اول به کلاس D معرفی شده است . (در اینجا A)به طور کلی شما نیازی به استفاده از این گونه ارث بری ندارید . گرچه این مقوله در mix-in مورد استفاده زیادی قرار می گیرد . Mix-in به معنای افزودن یک فیلد یا متد اضافی به هر کلاسی است که از آن والد ارث بری کند . (سعی کنید این کار را بسیار ساده و غیر پیچیده انجام بدهید . ممکن است در مراحل بالاتر در کشف اینکه این قطعه اطلاعات خاص از کدام کلاس وارد شده است دچار مشکل شوید !)به یاد داشته باشید که استفاده از یک فیلد primary key در همه ی کلاس های والد باعث ایجاد خطا می شود (id field). برای استفاده از وراثت چندگانه بهتر است از یک autofield در کلاس های والد استفاده کنید .class Article(models.Model): article_id = models.AutoField(primary_key=True) ... class Book(models.Model): book_id = models.AutoField(primary_key=True) ... class BookReview(Book, Article): passراه دیگر این است که از یک والد مشترک برای نگهداری فیلدهای AutoField استفاده کنید . این امر مستلزم استفاده از یک OneToOneField صریح از هر مدل به یک والد است . (منطور رابطه بین والد و پدربزرگ است و فرزند در اینجا نقشی ندارد) این از برخورد بین فیلد های خودکار ایجاد شده در میان فرزندان که به ارث می رسند جلوگیری خواهد کرد .به عبارت دیگر شما یک مدل A را تعریف می کنید و در آن pass قرار می دهید . سپس مدل B و C را ایجاد می کنید و در آنها از مدل A ارث بری میکنید . سپس مدل D را ایجاد میکنید و ارث بری چندگانه را میان D و B و C ایجاد میکنید . برای اینکار کافی است مدل D از B و C ارث بری کنند . در آخر باید در مدل های B و C فیلد OneToOneField را ایجاد کنید و آن را به مدل A ربط دهید . (باید parent_link = True قرار داده شود)این سری از کارها باعث می شود تا نیازی به ایجاد فیلد AutoField نداشته باشید . به مثال زیر نگاه کنید تا بهتر متوجه شوید :class Piece(models.Model): pass class Article(Piece): article_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True) ... class Book(Piece): book_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True) ... class BookReview(Book, Article): passمدل ها :حذف فیلد به ارث رسیده از والددر وراثت معمولی پایتون برای کلاس فرزند این رفتار مجاز است تا یک ویژگی به ارث رسیده از والد خود را لغو کند . این کار را معمولا با None قرار دادن آن ویژگی انجام می دهند . در جنگو این کار برای فیلد ها مجاز نیست . اگر کلاس والد شما abstarct نباشد و شما در آن فیلدی با نام author (برای مثال) داشته باشید ,شما نمی توانید در کلاس فرزند فیلدی با این نام یا حتی ویژگی ای با این نام تعریف کنید . (فقط در کلاس های غیر abstarct)در کلاس های والدی که abstract باشند ,این محدودیت وجود ندارد . فرزند اینگونه کلاس ها می توانند آن فیلد را بازنویسی کنند یا با تنظیم field_name = None (field_name نام فیلد شما است) آن را حذف کنند .نکته : manager های مدل ها از والد به ارث می رسند (در ارث بری نوع abstarct) . نادیده گرفتن فیلدی که در manager استفاده شده است و به کلاس فرزند به ارث رسیده است ,ممکن است باعث ایجاد مشکلاتی شود . در این خصوص در بخش manager بیشتر آشنا خواهید شد .گرچه نادیده گرفتن فیلد ها به ارث رسیده از مدل والد منجر به مشکلاتی در زمینه های serialization (در مبحث rest api) و مقدار دهی اولیه شی های جدید (اینکه کدام فیلد در _model._init مقدار دهی شود) می شود . اینها در پایتون معمولی وجود ندارند و به همین علت رفتار پایتون با آنها معمولی نخواهد بود . این باعث می شود تا ارث بری در جنگو کمی مشکل تر باشد .این محدودیت ها فقط برای فیلد ها اعمال می شوند . شما می توانید بسیار ساده ویژگی هایی که فیلد نیستند را بازنویسی کنید یا آنها را تغییر بدهید .گرچه پاراگراف بالا در مورد بعضی از ارث بری ها درست است . برای نمونه : اگر شما به صورت دستی خودتان نام ستون های جدول دیتابیس را تعیین کنید می توانید نام ستون یکسانی را در یک فرزند و کلاس جد آن برای ارث بری چندجدولی داشته باشد . (آنها ستون هایی در دو جدول متفاوت از یک پایگاه داده هستند !)اگر یک فیلد را در یک مدل جد لغو کنید ,جنگو یک FieldError را برای شما ایجاد میکند .در این جلسه به بررسی ارث بری مدل ها و انواع آن در جنگو به طور کامل پرداختیم . در جلسه بعدی درباره آرگومان های ورودی برای تنظیم فیلد های یک مدل در جنگو صحبت خواهیم کرد .