Repository: wagtail/wagtail

Issue:
Field value in Customized Admin Views for Snippets does not Show properly
I am converting ModelAdmin(Wagtail V5.0.2) class to SnippetViewSet(Wagtail V5.1.0).
I have a class, for example,

```py
class A(models.Model):
    name = models.CharField(max_length=255)
    weight = models.IntegerField(default=0)
    is_available = models.Boolean(default=False)

    class Meta:
        ordering = ('weight',)
```

I add the class to wagtail-admin

```py
class AViewSet(SnippetViewSet):
    model = A
    menu_label = 'A'
    list_display = ('name', ‘weight', 'is_avaialble')
```

But weight = 0 and is_available=False do not show properly in the view.

![image](https://github.com/wagtail/wagtail/assets/81170508/c3bc9920-4192-47d1-8bff-f2c0f3c173e9)

In previous Wagtail version, when I use ModelAdmin, 0 weight can be displayed and BooleanField can be displayed with icon (tick/cross)

![image](https://github.com/wagtail/wagtail/assets/81170508/7350e0ca-4e8b-4133-86ee-bb7be326610d)

Wagtail: 5.1.0
python: 3.10
Django: 4.2.4


Discussion:
Thanks for the report @aliceni81! I can confirm that the `0` values are not showing. Seems to be caused by the `if` check in the following template:

https://github.com/wagtail/wagtail/blob/db42d56beaa164e5b2c648f951281ebc10a9ddb7/wagtail/admin/templates/wagtailadmin/tables/cell.html#L2

For the `BooleanField` icon display, I don't think that's a built-in feature in ModelAdmin. Did you make any other customisations for displaying the field? Your screenshot shows the column is titled "Is gk filter", but your code refers to the `is_available` field.
@laymonage Thanks for your confirmation. Besides 0, value equals "False" also could not be shown.
Sorry to make you confused, the field in my project is a Boolean Field called "is_gk_filter", but I give an example with "is_available".
I don't many any other customization for BooleanField using ModelAdmin in my project.

Resolving patch:
diff --git a/wagtail/admin/ui/tables/__init__.py b/wagtail/admin/ui/tables/__init__.py
--- a/wagtail/admin/ui/tables/__init__.py
+++ b/wagtail/admin/ui/tables/__init__.py
@@ -243,6 +243,12 @@ def get_cell_context_data(self, instance, parent_context):
         return context
 
 
+class BooleanColumn(Column):
+    """Represents a True/False/None value as a tick/cross/question icon"""
+
+    cell_template_name = "wagtailadmin/tables/boolean_cell.html"
+
+
 class LiveStatusTagColumn(StatusTagColumn):
     """Represents a live/draft status tag"""
 


Test patch:
diff --git a/wagtail/snippets/tests/test_viewset.py b/wagtail/snippets/tests/test_viewset.py
--- a/wagtail/snippets/tests/test_viewset.py
+++ b/wagtail/snippets/tests/test_viewset.py
@@ -666,6 +666,8 @@ def test_custom_columns(self):
         self.assertContains(response, "Country code")
         self.assertContains(response, "Custom FOO column")
         self.assertContains(response, "Updated")
+        self.assertContains(response, "Modulo two")
+        self.assertContains(response, "Tristate")
 
         self.assertContains(response, "Foo UK")
 
@@ -677,8 +679,56 @@ def test_custom_columns(self):
 
         html = response.content.decode()
 
-        # The bulk actions column plus 4 columns defined in FullFeaturedSnippetViewSet
-        self.assertTagInHTML("<th>", html, count=5, allow_extra_attrs=True)
+        # The bulk actions column plus 6 columns defined in FullFeaturedSnippetViewSet
+        self.assertTagInHTML("<th>", html, count=7, allow_extra_attrs=True)
+
+    def test_falsy_value(self):
+        # https://github.com/wagtail/wagtail/issues/10765
+        response = self.get()
+        self.assertContains(response, "<td>0</td>", html=True, count=1)
+
+    def test_boolean_column(self):
+        self.model.objects.create(text="Another one")
+        response = self.get()
+        self.assertContains(
+            response,
+            """
+            <td>
+                <svg class="icon icon-success default w-text-positive-100" aria-hidden="true">
+                    <use href="#icon-success"></use>
+                </svg>
+                <span class="visuallyhidden">True</span>
+            </td>
+            """,
+            html=True,
+            count=1,
+        )
+        self.assertContains(
+            response,
+            """
+            <td>
+                <svg class="icon icon-error default w-text-critical-100" aria-hidden="true">
+                    <use href="#icon-error"></use>
+                </svg>
+                <span class="visuallyhidden">False</span>
+            </td>
+            """,
+            html=True,
+            count=1,
+        )
+        self.assertContains(
+            response,
+            """
+            <td>
+                <svg class="icon icon-help default" aria-hidden="true">
+                    <use href="#icon-help"></use>
+                </svg>
+                <span class="visuallyhidden">None</span>
+            </td>
+            """,
+            html=True,
+            count=1,
+        )
 
 
 class TestListExport(BaseSnippetViewSetTests):
diff --git a/wagtail/test/testapp/models.py b/wagtail/test/testapp/models.py
--- a/wagtail/test/testapp/models.py
+++ b/wagtail/test/testapp/models.py
@@ -1129,6 +1129,12 @@ class CountryCode(models.TextChoices):
     def __str__(self):
         return self.text
 
+    def modulo_two(self):
+        return self.pk % 2
+
+    def tristate(self):
+        return (None, True, False)[self.pk % 3]
+
     def get_preview_template(self, request, mode_name):
         return "tests/previewable_model.html"
 
diff --git a/wagtail/test/testapp/wagtail_hooks.py b/wagtail/test/testapp/wagtail_hooks.py
--- a/wagtail/test/testapp/wagtail_hooks.py
+++ b/wagtail/test/testapp/wagtail_hooks.py
@@ -17,7 +17,7 @@
 from wagtail.admin.search import SearchArea
 from wagtail.admin.site_summary import SummaryItem
 from wagtail.admin.ui.components import Component
-from wagtail.admin.ui.tables import UpdatedAtColumn
+from wagtail.admin.ui.tables import BooleanColumn, UpdatedAtColumn
 from wagtail.admin.views.account import BaseSettingsPanel
 from wagtail.admin.widgets import Button
 from wagtail.snippets.models import register_snippet
@@ -257,7 +257,14 @@ class FullFeaturedSnippetViewSet(SnippetViewSet):
     list_per_page = 5
     chooser_per_page = 15
     filterset_class = FullFeaturedSnippetFilterSet
-    list_display = ["text", "country_code", "get_foo_country_code", UpdatedAtColumn()]
+    list_display = [
+        "text",
+        "country_code",
+        "get_foo_country_code",
+        UpdatedAtColumn(),
+        "modulo_two",
+        BooleanColumn("tristate"),
+    ]
     list_export = [
         "text",
         "country_code",