0

私は、Product モデル、AppMedia モデル、および ProductMedia 結合テーブルを備えた単純な構造を持っています。

製品 (多数あり)

ProductMedia (1 つある) AppMedia

私が本当に望んでいるのは、AppMedia のメディア フィールドのサムネイルを Product のインライン フォームで表示することです。

たとえば、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 はこの方法で共有され、同じファイルの複数のアップロードを停止し、追加のメタデータ (ここには表示されていません) を画像と共に保存します。

4

2 に答える 2

0

私も同じ問題を抱えていました。私の試みの少なくとも1つがあなたのケースに役立つことを願っています:

この問題を(オーバーライドせずに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_valueForeignKeyRawIdWidget__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)
于 2012-10-31T14:07:24.800 に答える
-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

あなたの質問を正しく理解できたことを願っています。また、コードはテストされていませんが、動作するはずです。

于 2012-09-29T11:38:35.430 に答える