Django 区分查询集中的子项
Django Differentiating Children in Queryset
我有一个模型叫做 "Block"
class Block(models.Model):
zone = models.ForeignKey(Zone)
order = models.IntegerField()
weight = models.IntegerField()
block_type = models.CharField(max_length=32, blank=True)
class Meta:
ordering = ['order']
def __str__(self):
return "Block "+str(self.order)
Block 对象有继承自它的子对象。 ImageBlock、VideoBlock 等...我会随着项目的进行添加更多内容
# Children of Block Object
class TextBlock(Block):
content = models.TextField(blank=True)
class ImageBlock(Block):
content = models.ImageField(blank=True)
class VideoBlock(Block):
content = models.FileField(blank=True)
我需要根据块的顺序对块执行操作。如
呈现 TextBlock1
渲染图像块 1
呈现 TextBlock2
我使用 Block.objects.all() 的方式查询所有这些对象,然后遍历它们。当我这样做时,我如何区分每个对象是我的哪些对象?
如:
blockset = Block.objects.all()
for block in blockset:
if (**some way of differentiating if it's a TextBlock**):
print("This is a text block!")
知道我该怎么做吗?
非常感谢!
如果您不知道要获取的 class 的名称,可以在父模型上使用 Content Types。例如:
(未测试)
from django.contrib.contenttypes.models import ContentType
class Block(models.Model):
zone = models.ForeignKey(Zone)
order = models.IntegerField()
weight = models.IntegerField()
block_type = models.ForeignKey(ContentType, editable=False)
def save(self, *args, **kwargs):
if not self.id:
self.block_type = self._block_type()
super(Block, self).save(*args, **kwargs)
def __block_type(self):
return ContentType.objects.get_for_model(type(self))
def cast(self):
return self.block_type.get_object_for_this_type(pk=self.pk)
class Meta:
abstract = True
还要注意抽象基础 class 这意味着不会在数据库中创建模型。抽象字段将添加到子 class 的那些字段中,即
class TextBlock(Block):
content = models.TextField(blank=True)
但是,您不能查询本例中的抽象基class。如果这是你想要做的,那么简单地在你的基础上添加一个查找 class.
TEXT = 'TXT'
IMAGE = 'IMG'
VIDEO = 'VID'
BLOCK_CHOICES = (
(TEXT, 'Text Block'),
(IMAGE, 'Image Block'),
(VIDEO, 'Video Block'),
)
class Block(models.Model):
zone = models.ForeignKey(Zone)
order = models.IntegerField()
weight = models.IntegerField()
block_type = models.CharField(max_length=3, choices=BLOCK_CHOICES)
然后查询:Block.objects.filter(block_type='Text Block')
或者在你的例子中:
blockset = Block.objects.all()
for block in blockset:
if block.block_type == "Text Block":
print("This is a text block!")
我有一个模型叫做 "Block"
class Block(models.Model):
zone = models.ForeignKey(Zone)
order = models.IntegerField()
weight = models.IntegerField()
block_type = models.CharField(max_length=32, blank=True)
class Meta:
ordering = ['order']
def __str__(self):
return "Block "+str(self.order)
Block 对象有继承自它的子对象。 ImageBlock、VideoBlock 等...我会随着项目的进行添加更多内容
# Children of Block Object
class TextBlock(Block):
content = models.TextField(blank=True)
class ImageBlock(Block):
content = models.ImageField(blank=True)
class VideoBlock(Block):
content = models.FileField(blank=True)
我需要根据块的顺序对块执行操作。如
呈现 TextBlock1 渲染图像块 1 呈现 TextBlock2
我使用 Block.objects.all() 的方式查询所有这些对象,然后遍历它们。当我这样做时,我如何区分每个对象是我的哪些对象?
如:
blockset = Block.objects.all()
for block in blockset:
if (**some way of differentiating if it's a TextBlock**):
print("This is a text block!")
知道我该怎么做吗?
非常感谢!
如果您不知道要获取的 class 的名称,可以在父模型上使用 Content Types。例如:
(未测试)
from django.contrib.contenttypes.models import ContentType
class Block(models.Model):
zone = models.ForeignKey(Zone)
order = models.IntegerField()
weight = models.IntegerField()
block_type = models.ForeignKey(ContentType, editable=False)
def save(self, *args, **kwargs):
if not self.id:
self.block_type = self._block_type()
super(Block, self).save(*args, **kwargs)
def __block_type(self):
return ContentType.objects.get_for_model(type(self))
def cast(self):
return self.block_type.get_object_for_this_type(pk=self.pk)
class Meta:
abstract = True
还要注意抽象基础 class 这意味着不会在数据库中创建模型。抽象字段将添加到子 class 的那些字段中,即
class TextBlock(Block):
content = models.TextField(blank=True)
但是,您不能查询本例中的抽象基class。如果这是你想要做的,那么简单地在你的基础上添加一个查找 class.
TEXT = 'TXT'
IMAGE = 'IMG'
VIDEO = 'VID'
BLOCK_CHOICES = (
(TEXT, 'Text Block'),
(IMAGE, 'Image Block'),
(VIDEO, 'Video Block'),
)
class Block(models.Model):
zone = models.ForeignKey(Zone)
order = models.IntegerField()
weight = models.IntegerField()
block_type = models.CharField(max_length=3, choices=BLOCK_CHOICES)
然后查询:Block.objects.filter(block_type='Text Block')
或者在你的例子中:
blockset = Block.objects.all()
for block in blockset:
if block.block_type == "Text Block":
print("This is a text block!")