You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Wagtail 4中FieldPanel关联ForeignKey的ID字段错误问题

Wagtail 4.0.4中ForeignKey指定to_field后FieldPanel报错的解决方法

问题场景

你在Wagtail 4.0.4中配置了以下代码:

@register_snippet
class Copyright(models.Model):
   class CopyrightType(models.TextChoices):
      PH1 = "PH1", _("Phase 1")
      PH2 = "PH2", _("Phase 2")

   type = models.CharField(
       max_length=3,
       choices=CopyrightType.choices,
       unique=True,
       )

class ReportPage(Page):
    copyright = models.ForeignKey(
        Copyright,
        to_field="type",
        default="PH2",
        on_delete=models.SET_DEFAULT,
    )

原本运行正常,但当给ReportPage的promote_panels添加FieldPanel("copyright")后:

class ReportPage(Page):
    copyright = models.ForeignKey(
        Copyright,
        to_field="type",
        default="PH2",
        on_delete=models.SET_DEFAULT,
    )

    promote_panels = Page.promote_panels + [
        FieldPanel("copyright"),
    ]

触发了错误:

ValueError: Field 'id' expected a number but got 'PH2'.

解决方法

方法1:使用SnippetChooserPanel(推荐)

因为Copyright是注册的snippet,直接用Wagtail提供的SnippetChooserPanel并指定field_name参数,让它识别你设置的type字段:

from wagtail.snippets.edit_handlers import SnippetChooserPanel

class ReportPage(Page):
    copyright = models.ForeignKey(
        Copyright,
        to_field="type",
        default="PH2",
        on_delete=models.SET_DEFAULT,
    )

    promote_panels = Page.promote_panels + [
        SnippetChooserPanel("copyright", field_name="type"),
    ]

方法2:自定义ModelChoiceField适配FieldPanel

如果必须使用FieldPanel,可以自定义表单字段,指定to_field_name为type:

from django.forms import ModelChoiceField
from wagtail.admin.panels import FieldPanel

class CopyrightModelChoiceField(ModelChoiceField):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.to_field_name = "type"

class ReportPage(Page):
    copyright = models.ForeignKey(
        Copyright,
        to_field="type",
        default="PH2",
        on_delete=models.SET_DEFAULT,
    )

    promote_panels = Page.promote_panels + [
        FieldPanel("copyright", widget=CopyrightModelChoiceField(queryset=Copyright.objects.all())),
    ]

原因说明

Wagtail默认的FieldPanel处理ForeignKey时,会使用Django原生的ModelChoiceField,这个组件默认以主键(id)作为提交的字段值。但你的ForeignKey指定了to_field="type",提交时会传递PH2(type字段的值)去匹配id字段,导致类型不匹配的错误。通过上述方法指定使用type字段作为关联标识,就能解决这个问题。


内容的提问来源于stack exchange,提问作者jcuot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 11:00:55