Tom Edward
Tom Edward

Reputation: 3

wagtail snippet index page does not show image itself, but show image name

My snippet has a image field. The image is not shown in snippet admin index page.


class Product(ClusterableModel):
    name = models.CharField(max_length=255)
    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    sku = models.CharField(max_length=128)
    number = models.IntegerField()

    def schedule(self):
        return format_html("<a>First</a> | <a>Second</a>")

    panels = [
        FieldPanel("name"),
        FieldPanel("image"),
        FieldPanel("sku"),
        FieldPanel("number"),
    ]

    def __str__(self):
        return self.name

class ProductViewSet(SnippetViewSet):
    model = Product
    menu_icon = "pilcrow"  # change as required
    menu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)
    add_to_admin_menu = True  # or False to exclude your model from the menu

    search_fields = ("name", "sku")
    list_display = ("name", "sku", "image", "number", "schedule")

register_snippet(ProductViewSet)

it shows like this example index admin page

I want to show the image itself, not the image name.

Upvotes: 0

Views: 56

Answers (2)

Rich - enzedonline
Rich - enzedonline

Reputation: 1303

You need to create a custom column type for your index view that handles displaying the image. You're seeing the name because it's the __str__() value of the Image object.

I use the following on my sites:

from wagtail.admin.ui.tables import TitleColumn
from django.utils.safestring import mark_safe

class ImageColumn(TitleColumn):
    def get_cell_context_data(self, instance, parent_context):
        context = super().get_cell_context_data(instance, parent_context)
        try:
            context['value'] = mark_safe(
                context['value'].get_rendition('height-50').img_tag({'class':"show-transparency"})
                )
        except:
            context['value'] = mark_safe(
                '''
                <svg class="icon icon-image" height="50px" 
                     viewBox="0 0 24 24" aria-hidden="true">
                    <use href="#icon-image"></use>
                </svg>
                '''
                )
        return context

It inherits Wagtail's TitleColumn - this allows it to be clickable if you use it in a custom chooser.

It overrides the get_cell_context_data() method to return the HTML for the rendered image. I've set height-50 to scale the image down without cropping (my preference) - use fill50x50 if you want square thumbnails. It adds the show-transparency css class to make viewing images with transparent backgrounds easier.

In the case that there is a problem with the rendition, or the image doesn't exist, the default image icon is rendered in place.

To use in your list view, you can use something like:

class ProductViewSet(SnippetViewSet):
    model = Product
    list_display = [
        "title", 
        "sku", 
        ImageColumn("image"), 
        UpdatedAtColumn()
    ]

register_snippet(ProductViewSet)

If you define your list display in the snippet viewset like this, you cannot set a custom column type in the first column. The view will be rendered without a link or action button set on each item. If you want to change that, you need to dive into creating a custom SnippetViewSet that calls a custom generic view and handles this for your own case.

Upvotes: 0

Girish Badgujar
Girish Badgujar

Reputation: 11

In Wagtail, when you have a snippet that includes an image field, the snippet index page will typically display the image field's filename rather than the image itself. To display the image directly in the snippet index page, you'll need to customize the list_display in your Wagtail snippet model admin.

Upvotes: 0

Related Questions