I'm trying to automatically fill in a specific charblock on a streamfield I have created on save and I can get it to change but not save because when the page refreshes the new data is not there.
def save(self, *args, **kwargs):
if kwargs.get('update_fields'):
if self.auto_update:
for product in self.product_details.raw_data:
product_name = product['value']['product_name']
product_url = product['value']['product_url']
# I'm trying to set the field data here
product['value']['product_snippet_url'] = 'Test'
# when I print, I see the 'Test' value in the dict
print(product)
else:
# Do stuff on publish()
pass
return super().save(*args, **kwargs)
# Streamfield Block
class ProductNameAndUrlBlock(blocks.StructBlock):
product_name = blocks.CharBlock(required=True, help_text='Add product name')
product_url = blocks.URLBlock(required=True, help_text='Add Product URL')
product_snippet_url = blocks.CharBlock(required=False, help_text='Link to snippet')
The above code is for testing purposes, my end goal is to insert the url of the related snippet there and then use JS to turn it into a button so when someone clicks on it, it links to the snippet page.
Writing back to the stream's raw_data
property will not reliably save the data. raw_data
is a "backup" copy of the data as retrieved from the database, in a simplified format - for example, a PageChooserBlock value is stored there as a plain ID rather than a Page object. Once data is read or written through the stream's standard methods (e.g. looping over for block in self.product_details
or writing self.product_details[0] = ...
), the raw_data
entry is treated as stale and not looked at again.
The correct approach is to read and write the stream itself as a list, rather than going through raw_data
:
for product in self.product_details:
product_name = product.value['product_name']
product_url = product.value['product_url']
# I'm trying to set the field data here
product.value['product_snippet_url'] = 'Test'