模型 mixins
在相同情況下,不同的模型在產品生命週期中可以具有相同的欄位和相同的過程。要在沒有程式碼重複的情況下處理這些相似性,可以使用繼承。 mixin 設計模式不是繼承整個類,而是讓我們繼承( 或者說某些包括 )一些方法和屬性。我們來看一個例子:
class PostableMixin(models.Model):
class Meta:
abstract=True
sender_name = models.CharField(max_length=128)
sender_address = models.CharField(max_length=255)
receiver_name = models.CharField(max_length=128)
receiver_address = models.CharField(max_length=255)
post_datetime = models.DateTimeField(auto_now_add=True)
delivery_datetime = models.DateTimeField(null=True)
notes = models.TextField(max_length=500)
class Envelope(PostableMixin):
ENVELOPE_COMMERCIAL = 1
ENVELOPE_BOOKLET = 2
ENVELOPE_CATALOG = 3
ENVELOPE_TYPES = (
(ENVELOPE_COMMERCIAL, 'Commercial'),
(ENVELOPE_BOOKLET, 'Booklet'),
(ENVELOPE_CATALOG, 'Catalog'),
)
envelope_type = models.PositiveSmallIntegerField(choices=ENVELOPE_TYPES)
class Package(PostableMixin):
weight = models.DecimalField(max_digits=6, decimal_places=2)
width = models.DecimalField(max_digits=5, decimal_places=2)
height = models.DecimalField(max_digits=5, decimal_places=2)
depth = models.DecimalField(max_digits=5, decimal_places=2)
要將模型轉換為抽象類,你需要在其內部 Meta
類中提及 abstract=True
。Django 不為資料庫中的抽象模型建立任何表。但是對於模型 Envelope
和 Package
,將在資料庫中建立相應的表。
此外,在一個以上的模型中需要一些模型方法。因此,可以將這些方法新增到 mixin 中以防止程式碼重複。例如,如果我們建立一個方法來將交付日期設定為 PostableMixin
,則可以從其兩個子項訪問:
class PostableMixin(models.Model):
class Meta:
abstract=True
...
...
def set_delivery_datetime(self, dt=None):
if dt is None:
from django.utils.timezone import now
dt = now()
self.delivery_datetime = dt
self.save()
這個方法可以用於以下兒童:
>> envelope = Envelope.objects.get(pk=1)
>> envelope.set_delivery_datetime()
>> pack = Package.objects.get(pk=1)
>> pack.set_delivery_datetime()