【问题标题】:Wagtail - customise FieldPanel to show results for current LocaleWagtail - 自定义 FieldPanel 以显示当前区域设置的结果
【发布时间】:2022-08-22 22:37:11
【问题描述】:

我有一个启用 i18n 并使用 wagtail-localize 的站点。在编辑(或创建)页面的原始语言时,如果您使用标准 FieldPanel,所有 sn-ps 都会显示每种语言的值。使用 SnipperChooserPanel 不是一个选项,因为模型中有很多 ParentalManytoManyFields,对于编辑器来说太混乱了。

这就是模型和 sn-p 的构建方式。

@register_snippet
class Level(TranslatableMixin):
    name = models.CharField(max_length=255)
    def __str__(self):
        return self.name

    class Meta:
        verbose_name = \"Educational Level\"
        unique_together = (\'translation_key\', \'locale\')

class Activity(Page):
       ...
       level = ParentalManyToManyField(Level, verbose_name=\'Education level\', blank=True)

        MultiFieldPanel([
           ....
            FieldPanel(\'level\', widget=forms.CheckboxSelectMultiple),
        ])

我正在尝试解决如何子类化FieldPanel,以便它使用页面的语言环境来过滤 sn-p 查询集。

我使用limit_choices_to kwarg for ParentalManyToManyField 对此有hacky/临时解决方案,但我只能按用户语言而不是页面语言进行过滤。

def limit_lang_choice():
    limit = models.Q(locale__language_code=get_language())
    return limit

    标签: python django wagtail wagtail-localize


    【解决方案1】:

    原来语言环境潜伏在BoundPanel.instance

    这是一个将根据区域设置进行过滤的选择面板。它将匹配该字段的默认面板类型,或者您可以使用适当的表单小部件(CheckboxSelectMultipleRadioSelectSelectSelectMultiple 之一)覆盖。设置typed_choice_field=True 以强制Select 进入下拉小部件(默认为列表)。

    from django.core.exceptions import ImproperlyConfigured
    from django.forms.models import ModelChoiceIterator
    from django.forms.widgets import (CheckboxSelectMultiple, RadioSelect, Select,
                                      SelectMultiple)
    from django.utils.translation import gettext_lazy as _
    from wagtail.admin.panels import FieldPanel
    
    
    class LocalizedSelectPanel(FieldPanel):
        """
        Customised FieldPanel to filter choices based on locale of page/model being created/edited
        Usage: 
        widget_class - optional, override field widget type
                     - should be CheckboxSelectMultiple, RadioSelect, Select or SelectMultiple
        typed_choice_field - set to True with Select widget forces drop down list 
        """
    
        def __init__(self, field_name, widget_class=None, typed_choice_field=False, *args, **kwargs):
            if not widget_class in [None, CheckboxSelectMultiple, RadioSelect, Select, SelectMultiple]:
                raise ImproperlyConfigured(_(
                    "widget_class should be a Django form widget class of type "
                    "CheckboxSelectMultiple, RadioSelect, Select or SelectMultiple"
                ))
            self.widget_class = widget_class
            self.typed_choice_field = typed_choice_field
            super().__init__(field_name, *args, **kwargs)
    
        def clone_kwargs(self):
            return {
                'heading': self.heading,
                'classname': self.classname,
                'help_text': self.help_text,
                'widget_class': self.widget_class,
                'typed_choice_field': self.typed_choice_field,
                'field_name': self.field_name,
            }
    
        class BoundPanel(FieldPanel.BoundPanel):
            def __init__(self, **kwargs):
                super().__init__(**kwargs)           
                if not self.panel.widget_class:
                    self.form.fields[self.field_name].widget.choices=self.choice_list
                else:
                    self.form.fields[self.field_name].widget = self.panel.widget_class(choices=self.choice_list)
                if self.panel.typed_choice_field:
                    self.form.fields[self.field_name].__class__.__name__ = 'typed_choice_field'
                pass
    
            @property
            def choice_list(self):
                self.form.fields[self.field_name].queryset = self.form.fields[self.field_name].queryset.filter(locale_id=self.instance.locale_id)
                choices = ModelChoiceIterator(self.form.fields[self.field_name])
                return choices
    

    因此,在您的 Activity 课程中,您可以使用

    LocalizedSelectPanel(
        'level', 
        widget_class=CheckboxSelectMultiple, 
        ),
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-05
      • 1970-01-01
      • 1970-01-01
      • 2020-01-08
      • 1970-01-01
      • 2022-06-20
      相关资源
      最近更新 更多