Search code examples
djangowagtailwagtail-streamfield

Using Wagtail with the contrib_Table_block doesn't seem to work the same as other fields


I've been following the reference in the wagtail docs on the Table_block contrib setup. The suggested method is to make this an insert to StreamField, which works fine for me for every type of block or field except TableBlock().When using Table_block via either the docs or inserting it into an already working tutorial, it doesn't hook into the database data. In other words, most of my pages will be populated from database fields into tables. So, using the Table_Block() or TypedTableBlock() blocks makes the most sense. Whenever I do that, I get table setup info rather than data in the table. I took a simple Streamfield tutorial and inserted TableBlock() as an insert into StreamField as the reference suggests. Here is my code: `

from django.db import models
from wagtail import blocks
from wagtail.models import Page
from wagtail.search import index
from wagtail.fields import StreamField
from wagtail.admin.panels import FieldPanel

from wagtail.contrib.table_block.blocks import TableBlock


class ScriptsPage(Page):

    template = 'scripts/scripts.html'

    script_content = StreamField([
        ('paragraph', models.Scripts()),
    ],
    )

    content_panels = Page.content_panels + [
        FieldPanel('script_content'),
    ]


class Scripts(TableBlock):
    table = (
        [
            # ('script_select', blocks.CharBlock(max_length=20)),
            ('script_name', blocks.CharBlock(max_length=20)),
            ('script_desc', blocks.CharBlock(max_length=200)),
            # body = blocks.RichTextBlock(blank=True, name="body")
            ('script_path',  blocks.CharBlock(max_length=20)),
            ('script_file', blocks.CharBlock(max_length=20)),
            ('script_args', blocks.CharBlock(max_length=100)),
            ('script_output_json', blocks.CharBlock(max_length=200)),
            ('script_on_demand', blocks.CharBlock(max_length=50)),
            ('script_sched_name', blocks.CharBlock(max_length=50)),
            ('script_send_output', blocks.CharBlock(max_length=50)),
            ('script_out_emails', blocks.CharBlock(max_length=50)),
        ]
    )

`

The template code is simply:
{% load i18n wagtailcore_tags %}
{% load static %}
<div>
    <table id="fresh-table" class="table">
        <thead>
        </thead>
        <tbody>
        <tbody>
          {% include_block scripts_content %}
        </tbody>
    </table>
</div>

Django 5.x, wagtail 6.x, using python 3.12 in venv.

A blank table then shows up in the admin page when I edit. This content is a knowledgebase of scripts being used actively and what they do, btw. All of these pages are KB articles using tables in the same way. The output I get is this:

Scripts table {'cell': [], 'data': [[None, None, None], [None, None, None], [None, None, None]], 'mergeCells': [], 'table_caption': 'External script setup:', 'first_col_is_header': False, 'table_header_choice': 'row', 'first_row_is_table_header': True}

That obviously is not at all what I'm expecting. I was expecting a table that lists active rows in the DB, and to be able to insert an edit button at some point to edit the data. Obviously the TableBlock is different, but there doesn't seem to be docs on HOW it's different, and I've tried tying this to a model in 10 different ways with no luck. I always get the same output. Others probably pick this up readily, but I'm new to wagtail. Not new to Django in general, but this is my first time using wagtail because I want the KB to be something people can easily add pages and data to.

Thanks all!

I tried making a direct Model for one thing, using:

class ScriptsTable(models.Model): Then defining each field, and adding it to the streamfield in the same way as above. This doid not change the output.

I also tried iterating through the table data int he template, whinking that this may not be a fully automated field like the others. Basically like this:

        <tbody>
          {% include_block scripts_content %}
          {% for i in scripts_content.table %}
            <tr>
              {% for f in i.scripts_content.table %}
                <td></td>
              {% endfor %}
              </tr>
          {% endfor %}
            <tr class="active-row">
            </tr>
        </tbody>

I also tried substituting a StructBlock instead, thinking this was an integration problem with StreamField. The odd thing is that nothing I've tried has changed the output or the fact that the makemigrations doesn't recognize new fields, which tends to indicate it doesn't even recognize the table is hooked to live data.


Solution

  • I don't think TableBlock or TypedTableBlock are what you are looking for. Both of them are for allowing editors to create tables by typing into the admin interface. Both of those blocks store their data in the JSON for the inclosing StreamField.

    most of my pages will be populated from database fields into tables

    If this is your goal, you should pull the data out of the database in a get_context method and use a custom template to display the data. You can do that directly in the page, as shown in the example in the tutorial. Or you can create a StructBlock that can do the database query and specify a custom template for rendering the information. The advantage of the StructBlock is that editors can now place the table where ever they want on the page.