为什么 MyPage._meta.get_field("title").verbose_name 更改了 Wagtail 中所有标题的标签?

Why MyPage._meta.get_field("title").verbose_name changes all the titles' labe in Wagtail?

我的 Wagtail 项目中有几个应用程序,其中之一是 "news",其中包含新闻(页面)。我想在管理员中将标题的标签 "title" 覆盖为 "headline"。

News._meta.get_field("title").verbose_name = "Headline"

因此,我在所有应用和页面中获得了所有标题的标签 "Headline"。为什么我有这种奇怪的效果?

更新:

# news/models.py

class NewsDetails(Page):
    template = "news/news_details.html"

    news_text = RichTextField(features=['h2', 'h3', 'bold', 'italic', 'link', 'ol', 'ul',])
    news_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
    )

    content_panels = Page.content_panels + [
        ImageChooserPanel("news_image"),
        FieldPanel("news_text")
    ]

    class Meta:
        verbose_name = "News"

    parent_page_types = ['news.NewsList']


NewsDetails._meta.get_field("title").verbose_name = "Headline"

这种方法的问题在于,当您 运行 执行 django-admin.py makemigrations 命令时,Django 将为 Wagtail 核心生成迁移(即使它是通过 pip 安装的)。

为避免这种情况,最好在 NewsDetails 模型中使用自定义 base_form_class。这种方法也适用于更改其他属性,例如 help_text

from wagtail.admin.forms import WagtailAdminPageForm

class NewsDetailsForm(WagtailAdminPageForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Manually edit the default form's title attributes:
        title = self.fields['title']
        title.verbose_name="Headline"
        title.help_text="Some headline..."


class NewsDetails(Page):
    template = "news/news_details.html"

    news_text = RichTextField(features=['h2', 'h3', 'bold', 'italic', 'link', 'ol', 'ul',])
    news_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
    )

    content_panels = Page.content_panels + [
        ImageChooserPanel("news_image"),
        FieldPanel("news_text")
    ]

    class Meta:
        verbose_name = "News"

    parent_page_types = ['news.NewsList']

    # Important line below:
    base_form_class = NewsDetailsForm

对 Nathan 的回答稍作改动,解决了 Valery 的 verbose_name 无效问题。设置 title.label 而不是 title.verbose_name:

class NewsDetailsForm(WagtailAdminPageForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Manually edit the default form's title attributes:
        title = self.fields['title']
        title.label = "Headline"
        title.help_text = "Some headline..."

原因是我们现在处理的是 django.forms.Field 而不是 django.db.models.Field。请参阅 django.db.models.Field.formfield() 中的代码:

    def formfield(self, form_class=None, choices_form_class=None, **kwargs):
        """Return a django.forms.Field instance for this field."""
        defaults = {
            'required': not self.blank,
            'label': capfirst(self.verbose_name),
            'help_text': self.help_text,
        }

        ...

        return form_class(**defaults)

也许可以在模型 class 中添加一个 init 方法,如下所示:

class NewsDetails(Page):
...
    def __init__(self, *args, **kwargs):
        super(NewsDetails, self).__init__(*args, **kwargs)
        self._meta.get_field('title').verbose_name = 'Headline'
...

我认为必须对模型中定义的所有 classes 执行此操作,否则,从 Page[=20= 子classed classes ] 将具有最后更新的标签。例如,在这里,如果我 subclass Page 创建一个新的 class,我将看到 Headline 作为标题标签,而我应该看到默认标签 Title.