Austin Grandt
Austin Grandt

Reputation: 33

Get All StreamField Blocks of Specific Type

I have created a custom photoBlock to embed photos in a blog post. I am trying to create a template tag that would allow me to get every photoBlock that is stored in the database, almost like you query pages in Wagtail. I would prefer not to have to create a separate page for every photo, but instead be able to display them on a different page if possible via the template tag.

class photoBlock(blocks.StructBlock):
     date = blocks.DateBlock("Date Image Was Taken")
     location = blocks.CharBlock(max_length=100)
     image = ImageChooserBlock()
     latitude = blocks.DecimalBlock(max_digits=9, decimal_places=6)
     longitude = blocks.DecimalBlock(max_digits=9, decimal_places=6)
     description = blocks.RichTextBlock()

I am able to get the following to work, but it feels like the query is very heavy and will get bogged down once I have a bunch of posts.

for page in BlogPage.objects.all():
     for block in page.body.stream_data:
          if block['type'] == 'photoBlock':
               return block

Is there any better way to query a specific block from Streamfield? Anytime I try something like this

photoBlock.objects.all()

I always get an error response that photoBlock doesn't have attribute Object. Any ideas?

Upvotes: 1

Views: 1988

Answers (3)

MrWaffles
MrWaffles

Reputation: 1

Update for anyone searching for the same thing: ever since Wagtail 2.12, the original answer does not work as stream_data as a property of StreamValue was deprecated. You can use the following to achieve the same thing:

def find_block(block_name):
    for page in YourPageModel:
        for block in page.body:
            if block.block_type == block_name:
                print('@@@ Found one: ' + str(block.block_type) + ' at page: ' + str(page))

Upvotes: 0

Johan
Johan

Reputation: 390

No real answer here either. What you could do to improve your query is to check if the string 'photoBlock' is present in the page body. The stream data is simply stored as a JSON string so that would yield only pages which contain that block.

Upvotes: 0

gasman
gasman

Reputation: 25237

Unfortunately there's no more efficient way to query StreamField blocks than looping over all the pages that contain them, as you're doing in your code snippet. This is a limitation of StreamField's implementation - the data is stored as a string of JSON on the page object, rather than the blocks being "true" database objects.

Upvotes: 1

Related Questions