我有一个简单的结构,包含Product模型,AppMedia模型和ProductMedia连接表。
产品(有很多)ProductMedia
ProductMedia(有一个)AppMedia
我真正想要的是在Product中以内联形式查看AppMedia媒体字段的缩略图。
e.g。在Django admin中编辑产品,显示StackedInline表单。这包含(目前)所有AppMedia的下拉(选择)。
我需要的是缩略图。
任何帮助表示感谢。
我确信这并不困难,但我很挣扎。将缩略图放入AppMedia表格(这是媒体ImageField所在的位置)非常简单,但不适用于将AppMedia用作ForeignKey的ProductMedia表单。
基本型号......
class Product(models.Model):
name = models.CharField(max_length=100)
class AppMedia(models.Model):
media = models.ImageField(upload_to=appmedia_upload_to) #appmedia_upload_to defined elsewhere)
class ProductMedia(models.Model):
title = models.CharField(max_length=150)
media = models.ForeignKey(AppMedia)
media_order = models.IntegerField(default=0)
product = models.ForeignKey(Product)
以这种方式共享AppMedia以停止同一文件的多次上传,并且还存储图像中的额外元数据(此处未显示)。
答案 0 :(得分:0)
我有同样的问题。我希望至少有一次尝试可以用于你的案子:
我首次尝试解决此问题(不覆盖ForeignKeyRawIdWidget
)是:
form
属性,其中应显示缩略图但是我放弃了这个解决方案,因为我认为我必须在表单的构造函数中将缩略图数据注入给定字段,我不认为这是一个很好的解决方案。
我的下一个解决方案是在某些字段中使用MultiWidget
。在这种情况下,我不需要添加另一个字段来形成,我将需要在窗口小部件中显示缩略图所需的数据,而无需在构造函数中注入它们。
class ThumbnailMultiWidget(MultiWidget):
def decompress(self, value):
#has to be overriden
return [None,None]
class ThumbnailWidget(Widget):
def render(self, name, value, attrs=None):
#not quite sure what is in `value`, I've not been so far
return '<img src="%s"/>' % value.url
class PhotoInlineForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(PhotoInlineForm, self).__init__(*args, **kwargs)
wdgts = [self.fields['media'].widget, ThumbnailWidget()]
self.fields['media'].widget = ThumbnailMultiWidget(widgets=wdgts)
class Meta:
model = RecipePhoto
但是我也放弃了这个解决方案,因为我发现实际上在ForeignKeyRawIdWidget
(我使用的小部件)中有一个实例的表示,我需要显示缩略图所需的所有数据。这是我的最终解决方案:
因为我的内联项目有raw_id_field
用于选择内联记录,我可以简单地覆盖label_for_value
中的方法ForeignKeyRawIdWidget
,该方法用于表示现有的内联记录。通常它是__unicode__
(我认为)。我继承了ForeignKeyRawIdWidget
并重写此方法以显示图片缩略图:
class PhotoForeignKeyRawIdWidget(ForeignKeyRawIdWidget):
def label_for_value(self, value):
key = self.rel.get_related_field().name
try:
obj = self.rel.to._default_manager.using(self.db).get(**{key: value})
except (ValueError, self.rel.to.DoesNotExist):
return ''
else:
"""
there's utilized sorl.thumbnail, but you can return st like this:
<img src='%s' /> % obj.media.url
"""
return Template("""{% load thumbnail %}
{% thumbnail image.image "120x120" crop="center" as one %}
<img src="{{ one.url }}" />
{% endthumbnail %}""").render(Context({
'image': obj
}))
class AppMediaInlineAdmin(admin.TabularInline):
model = AppMedia
extra = 1
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
if db_field.name == 'media':
db = kwargs.get('using')
kwargs['widget'] = PhotoForeignKeyRawIdWidget(db_field.rel, self.admin_site, using=db)
return super(AppMediaInlineAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
答案 1 :(得分:-1)
您应该查看外键的related_name参数,这样您就可以反向访问ProductMedia,即如果您将ProductMedia模型更改为:
class ProductMedia(models.Model):
title = models.CharField(max_length=150)
media = models.ForeignKey(AppMedia)
media_order = models.IntegerField(default=0)
product = models.ForeignKey(Product, related_name='media')
您可以访问产品型号中的媒体对象,这样您就可以将其放入管理员的在线表单中。即你会有(为了更简单的解释,我把ImageField放在ProductMedia中):
class Product(models.Model):
name = models.CharField(max_length=100)
def admin_image(self):
return '<img src="%s"/>' % (self.media.all()[0].image.url)
admin_image.allow_tags = True
class ProductMedia(models.Model):
title = models.CharField(max_length=150)
image = models.ImageField(upload_to=appmedia_upload_to) #appmedia_upload_to defined elsewhere)
media_order = models.IntegerField(default=0)
product = models.ForeignKey(Product, related_name='media')
然后在你的admin.py中:
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'admin_image')
admin.site.register(models.Product, ProductAdmin)
https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.related_name
希望我能正确理解你的问题,这有帮助。此外,代码未经过测试,但我确信它应该可以使用。