How can I create Page and set its StreamField value programmatically?
Asked Answered
C

2

8

I want to create a BlogPage programmatically in wagtail with setting its StreamField value. I can set heading field. But I'm getting AttributeError: 'unicode' object has no attribute 'source' when I try to set the paragraph field. I want to set an image too.

This is my BlogPage model.

models.py

class BlogPage(Page):
template = 'wagtail/test_page.html'
author = models.CharField(max_length=255)
date = models.DateField("Post date")
body = StreamField([
    ('heading', blocks.CharBlock(classname="full title")),
    ('paragraph', blocks.RichTextBlock()),
    ('image', ImageChooserBlock()),
])

content_panels = Page.content_panels + [
    FieldPanel('author'),
    FieldPanel('date'),
    StreamFieldPanel('body'),
]

this my code to create page by running this script.

create_page.py

new_image_page = BlogPage(
    title='Blog',
    slug='michael',
    author='michael',
    date='2017-12-13',
    body=[('heading','New Heading'), ('heading','New Heading 23232'), ('paragraph','My Paragraph')]
)

directory_page = Page.objects.get(slug='home')
directory_page.add_child(instance=new_image_page)
revision = new_image_page.save_revision()
revision.publish()
new_image_page.save()
Chirpy answered 13/12, 2017 at 7:57 Comment(0)
C
2

At first I created a BlogPage using Wagtail admin interface with setting it's StreamField(heading etc.) manually. I checked the attribute of newly created BlogPage object using __dict__ in python shell. Then I got those results after filtering body StreamFieldPanel 'stream_data': [{u'type': u'heading', u'id': u'0ebe1070-d167-48a0-9c57-70e4ad068ae5', u'value': u'New Heading'}]. After seeing the structure of stream_data and getting suggestion to use json.dumps() from LB Ben Johnston's answer I got my solution.

Here is my solution.

import json

new_image_page = BlogPage(
   title='Blog',
   slug='michael',
   author='michael',
   date='2017-12-13',
   body = json.dumps([
       {u'type': u'heading', u'value': u'New Heading 23232'},
       {u'type': u'heading', u'value': u'New Heading 23232'},
       {u'type': u'paragraph', u'value': u'New Paragraph'},
       ])
)
Chirpy answered 13/12, 2017 at 14:49 Comment(2)
I have tried this but it shows this error. AttributeError: 'str' object has no attribute 'get_prep_value'Swords
@Md. Showkat Hossain Chy It would have been a nice gesture if you accepted LB Ben Jonsohn's answer that helped you figure it out, instead of adding the answer yourself.Decasyllabic
T
8

When adding the data for StreamField programmatically, it is better to enter the data as a raw json string. The data will be an array of dicts, where each dict contains a type and a value.

This should resolve any string conversion issues you run into also.

import json

new_image_page = BlogPage(
    title='Blog',
    slug='michael',
    author='michael',
    date='2017-12-13',
    body=json.dumps([
      {'type':'heading', 'value': 'New Heading'},
      {'type':'heading', 'value': 'New Heading 23232'},
      {'type':'paragraph', 'value': '<strong>My Paragraph</strong>'},
    ])
)

To add images, you will do a similar thing where the value is the pk (ID) of the image.

{'type': 'image', 'value': my_image.pk},

Thirtyone answered 13/12, 2017 at 8:50 Comment(3)
Thanks for your reply. now, it's giving this error {'type':'paragraph', 'value': '<strong>My Paragraph</strong>'}, TypeError: 'function' object has no attribute '__getitem__'Chirpy
Double check the full array passed into json.dumps, I fixed up my answer but it had some typos in the key for some of the dicts. Maybe also test out your json.dumps[...] in Python shell first to ensure it is formatted correctly.Thirtyone
It didn't work for me. when I changed it to body = json.dumps([ {u'type': u'heading', u'value': u'New Heading 23232'}, {u'type': u'heading', u'value': u'New Heading 23232'}, {u'type': u'paragraph', u'value': u'New Paragraph'}, ]) then it worked.Chirpy
C
2

At first I created a BlogPage using Wagtail admin interface with setting it's StreamField(heading etc.) manually. I checked the attribute of newly created BlogPage object using __dict__ in python shell. Then I got those results after filtering body StreamFieldPanel 'stream_data': [{u'type': u'heading', u'id': u'0ebe1070-d167-48a0-9c57-70e4ad068ae5', u'value': u'New Heading'}]. After seeing the structure of stream_data and getting suggestion to use json.dumps() from LB Ben Johnston's answer I got my solution.

Here is my solution.

import json

new_image_page = BlogPage(
   title='Blog',
   slug='michael',
   author='michael',
   date='2017-12-13',
   body = json.dumps([
       {u'type': u'heading', u'value': u'New Heading 23232'},
       {u'type': u'heading', u'value': u'New Heading 23232'},
       {u'type': u'paragraph', u'value': u'New Paragraph'},
       ])
)
Chirpy answered 13/12, 2017 at 14:49 Comment(2)
I have tried this but it shows this error. AttributeError: 'str' object has no attribute 'get_prep_value'Swords
@Md. Showkat Hossain Chy It would have been a nice gesture if you accepted LB Ben Jonsohn's answer that helped you figure it out, instead of adding the answer yourself.Decasyllabic

© 2022 - 2024 — McMap. All rights reserved.