django Wagtail-factories Pagechooser块不工作

8e2ybdfx  于 2023-05-08  发布在  Go
关注(0)|答案(1)|浏览(102)

我尝试为我的Navigation模型创建一个工厂,但是,这里的top_bar字段没有创建。该问题与URLChoiceStreamFactory相关,但无法解决。

models.py

from wagtail.models import Page
from wagtail import blocks
from django.db import models
from modelcluster.models import ClusterableModel
from wagtail.admin.panels import FieldPanel
from wagtail.models import PreviewableMixin
from wagtail.snippets.models import register_snippet
from django.utils.translation import gettext_lazy as _
from wagtail.fields import StreamField
from django import forms

class URLBlock(blocks.FieldBlock):
    def __init__(
            self,
            required=True,
            help_text=(
                    "Either a relative URL that begins with a forward slash or an absolute URL that begins with http, https, "
                    "tel, or mailto."
            ),
            max_length=None,
            min_length=None,
            **kwargs,
    ):
        self.field = forms.CharField(
            required=required,
            help_text=help_text,
            max_length=max_length,
            min_length=min_length,
        )
        super().__init__(**kwargs)

    class Meta:
        icon = "site"

class HomePage(Page):
    pass

class URLChoiceStream(blocks.StreamBlock):
    internal = blocks.PageChooserBlock(icon="doc-empty-inverse")

    class Meta:
        max_num = 1

class LinkBlock(blocks.StructBlock):
    name = blocks.CharBlock(max_length=128)
    url = URLChoiceStream()

    class Meta:
        icon = "link"
        label = _("Link")

class TopBar(blocks.StructBlock):
    title = blocks.CharBlock(label=_("Title"))
    top_bar_links = blocks.ListBlock(LinkBlock(), max_num=5)

    panels = [
        FieldPanel("title"),
        FieldPanel("top_bar_links"),
    ]

    class Meta:
        icon = "resubmit"

@register_snippet
class Navigation(ClusterableModel, PreviewableMixin):
    name = models.CharField(
        unique=True,
        max_length=256,
        help_text=_("This is used for internal reference only."),
    )
    top_bar = StreamField(
        [("top_bar", TopBar())],
        max_num=1,
        verbose_name=_("Top Bar"),
        null=True,
        blank=True,
        use_json_field=True,
    )

    panels = [
        FieldPanel("name"),
        FieldPanel("top_bar"),
    ]

    def __str__(self):
        return self.name

工厂.py

from home.models import Navigation, TopBar, LinkBlock, URLChoiceStream, HomePage
import factory
import wagtail_factories
from faker import Faker

faker = Faker()

class HomePageFactory(wagtail_factories.PageFactory):
    class Meta:
        model = HomePage

class HomePageChooserBlockFactory(wagtail_factories.PageChooserBlockFactory):
    page = factory.SubFactory(HomePageFactory)

class URLChoiceStreamFactory(wagtail_factories.StreamBlockFactory):
    internal = factory.SubFactory(HomePageChooserBlockFactory)

    class Meta:
        model = URLChoiceStream

class LinkBlockFactory(wagtail_factories.StructBlockFactory):
    name = factory.Faker("sentence", nb_words=2, variable_nb_words=False)
    url = factory.SubFactory(URLChoiceStreamFactory)

    class Meta:
        model = LinkBlock

class TopBarFactory(wagtail_factories.StructBlockFactory):
    title = faker.word()
    top_bar_links = wagtail_factories.ListBlockFactory(LinkBlockFactory)

    class Meta:
        model = TopBar

class NavFactory(factory.django.DjangoModelFactory):
    name = faker.name()
    top_bar = wagtail_factories.StreamFieldFactory(
        {
            "top_bar": factory.SubFactory(TopBarFactory),
        },
    )

    class Meta:
        model = Navigation

我调试了这个问题,HomePageFactory正在创建,但URLChoiceStreamFactory没有。Wagtail-factories文档非常小。无法在文档中找到相关部件。

eyh26e7m

eyh26e7m1#

URLChoiceStreamFactory.build()
这将根据设计构建一个空的StreamValue
URLChoiceStreamFactory.build(invalid_param=0)
*** wagtail_factories.builder.InvalidDeclaration: StreamFieldFactory declarations must be of the form <index>=<block_name>, <index>__<block_name>=value or <index>__<block_name>__<param>=value, got: invalid_param
构建非空StreamBlockFactory子类示例的方法是:

URLChoiceStreamFactory.build(**{'0': 'internal'})
# Out: <StreamValue [<block internal: <HomePage: Test page>>]>

构建包含非空StreamFieldFactory属性的DjangoModelFactory子类示例的方法是:

NavFactory.build(top_bar__0='top_bar')
# Out: <Navigation: Faker Name>
NavFactory.build(top_bar__0='top_bar').__dict__
# {'_state': <django.db.models.base.ModelState object at 0x10bd5a670>,
#  'id': None,
#  'name': 'Faker Name',
#  'top_bar': <StreamValue [
#   <block top_bar: StructValue([
#    ('title', 'fakerword'),
#    ('top_bar_links', <ListValue: []>)])>]>}
NavFactory.build(top_bar__0__top_bar__top_bar_links__0__url__0='internal').__dict__
# {'_state': <django.db.models.base.ModelState object at 0x000000000>,
#  'id': None,
#  'name': 'Faker Name',
#  'top_bar': <StreamValue [
#   <block top_bar: StructValue([
#    ('title', 'fakerword'),
#    ('top_bar_links', <ListValue: [
#     StructValue([
#      ('name', 'Faker sentence.'),
#      ('url', <StreamValue [<block internal: <HomePage: Test page>>]>)])]>)])>]>}

相关问题