добавить/изменить значение блоков в поле потока трясогузки из оболочки

У меня есть страница с одним телом StreamField и пользовательским блоком HeadingBlock:

class HeadingBlock(blocks.StructBlock):
    heading = blocks.CharBlock()
    cssid = blocks.CharBlock()
    ...

class CustomPage(Page):
    ...
    body = StreamField([
        ('heading', HeadingBlock()),
    ...

Мне нужно добавить новый charblock в атрибут заголовка HeadingBlock, но с помощью оболочки:

>>> from custom.models import CustomPage
>>> c = CustomPage.objects.all()[0]
>>> c.body[0].heading.value = "hello world" ??? this does not work

Кто-нибудь может помочь? большое спасибо!

РЕДАКТИРОВАТЬ: я упростил HeadingBlock, удалив ListBlock и попробовал:

>>> c.body[0].value
StructValue([('heading', u'hi'), ('cssid', u'man')])
>>> type(c.body[0].value)
<class 'wagtail.wagtailcore.blocks.struct_block.StructValue'>
>>> from wagtail.wagtailcore.blocks.struct_block import StructValue
>>> c.body[0].value = StructValue([('heading', u'hello'), ('cssid', u'world')])
>>> c.save()

но когда я захожу в интерфейс администратора, поля пусты. Я старался:

>>> c.body[0].block.child_blocks
OrderedDict([('heading', <wagtail.wagtailcore.blocks.field_block.CharBlock object at 0x7f4c2aaf9790>), ('cssid', <wagtail.wagtailcore.blocks.field_block.CharBlock object at 0x7f4c2aaf9a90>)])
>>> c.body[0].block.child_blocks['heading']
<wagtail.wagtailcore.blocks.field_block.CharBlock object at 0x7f4c2aaf9790>
>>> c.body[0].block.child_blocks['heading'].value
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'CharBlock' object has no attribute 'value'

Ничего не происходит, я не думаю, что это так сложно :-|


person Gianluca Esposito    schedule 15.11.2016    source источник
comment
вы сохраняете объект? Попробуйте c.save() в конце   -  person kristian    schedule 16.11.2016
comment
я пытаюсь упростить вопрос   -  person Gianluca Esposito    schedule 16.11.2016


Ответы (1)


Вывод StructValue([('heading', u'hi'), ('cssid', u'man')]) немного вводит в заблуждение — чтобы построить собственное StructValue, вам нужно передать соответствующий объект StructBlock. Другая проблема, с которой вы можете столкнуться, заключается в том, что значение StreamField не предназначено для обновления «на месте», как в c.body[0].value (хотя это может измениться в будущем выпуске трясогузки).

Рекомендуемый способ обновления StreamField — создать новое значение, состоящее из списка кортежей (block_type, value). Когда вы используете этот подход, StreamField позаботится о преобразовании значений в правильный тип, поэтому для StructBlock вы можете просто передать dict, а не создавать свой собственный StructValue:

c.body = [
    ('heading', {'heading': 'hi', 'cssid': 'man'})
]

Если в поле уже есть данные, которые вы хотите сохранить, более полный фрагмент кода может выглядеть примерно так:

new_body = []
for block_type, value in c.body:
    if block_type == 'heading':
        new_body.append(
            ('heading', {'heading': 'hello world', 'cssid': value['cssid']})
        )
    else:
        new_body.append((block_type, value))

c.body = new_body
person gasman    schedule 16.11.2016