模型 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()