Reputation: 33
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
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
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
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