我有以下模型来描述具有可选图像数量的绘画:
class Painting(Base, Seo, Timestamp):
artist = models.ForeignKey(Artist, related_name='paintings')
medium = models.ForeignKey(Medium)
def thumbnail(self):
thumbnail = self.images.filter(position=0)
if thumbnail.exists():
return thumbnail[0].thumbnail_html()
else:
return ''
thumbnail.allow_tags = True
class PaintingImage(models.Model):
painting = models.ForeignKey(Painting, related_name='images')
alt = models.CharField(max_length=100)
position = models.PositiveSmallIntegerField("Position", default=0)
# use pi.image = 'path/to/file' for direct access to the underlying image filename
image = models.ImageField(upload_to='paintings')
thumbnail = models.ImageField(upload_to='paintings')
这一切都很好,但管理列表视图很慢并且执行大量查询,因为它在绘画上调用 thumbnail(),它为每幅绘画对绘画图像进行单独的查询。
我试图覆盖 ModelAdmin 中的 queryset() 以有效地手动将图像附加到每个实例。list_display 中的 'thumbnail' 现在指向 PaintingAdmin 中的 thumbnail(self, obj) ,它读取存储的属性,但它不起作用 - 无法在下面的 thumbnail(self, obj) 中读取 obj.thumb:
class PaintingAdmin(admin.ModelAdmin):
fields = [('title', 'slug', 'display'),
'artist', ('categories', 'medium'), 'price', 'description', 'note',
('sold', 'reserved', ),
('height', 'width', 'frame_height', 'frame_width')
]
prepopulated_fields = {"slug": ("title",)}
inlines = [ImageInline, InvoiceInline]
list_display = ('title', 'artist', 'slug', 'medium', 'price',
'sold', 'reserved', 'display', 'created', 'thumbnail', 'invoice_link')
list_filter = ['display', 'sold', 'reserved', 'medium', PriceFilter]
search_fields = ['title', 'description', 'note', 'artist__last_name', 'artist__first_name']
date_hierarchy = 'created'
def thumbnail(self, obj):
return obj.thumb # error because it doesn't exist
def queryset(self, request):
"""make it more efficient by not getting painting image every time
"""
paintings = super(PaintingAdmin, self).queryset(request)
# get all images which are thumbnails
images = PaintingImage.objects.filter(
painting__in=paintings,
position=0
)
painting_id_to_thumbnail = {}
for image in images:
painting_id_to_thumbnail[image.painting_id] = image.thumbnail_html()
# attach thumbnail to each instance
for painting in paintings:
painting.thumb = painting_id_to_thumbnail.get(painting.id, '')
return paintings
我正在使用 django 1.5.2 和 python 2.7。