【问题标题】:Adding extra data to widget output for Foreignkey fields将额外数据添加到外键字段的小部件输出
【发布时间】:2014-10-28 17:17:59
【问题描述】:

假设我有以下模型...

class Person(models.Model):
   name = models.CharField()
   specialty = models.CharField()

class Team(models.Model):
    captain = models.ForeignKey(Person)
    vice_captain = models.ForeignKey(Person)

我有一个创建团队的表格...

class TeamForm(ModelForm):
     class Meta:
          model = Team
          widgets['vice_captain'] = MySelectWidget()

我对表格还有一个额外的限制,即副队长必须与队长具有相同的专长。我已经以 clean 等形式实现了检查,但希望 UI 能够“过滤”自身。我决定不使用 ajax 来填充/过滤字段,而是将 html 'data-' 标签添加到小部件输出中,然后使用 javascript 隐藏选项。

我编写了一个与 Select 小部件一起使用的小部件(和 javascript)。在这里(注意这是从我的实际代码中简化的,但应该可以)。

class Select_with_Data(forms.Select):
    # Not sure if this is necessary.
    allow_multiple_selected = False

    def render_option(self, selected_choices, option_value, option_label):

        # This paragraph is copied from django Select.
        option_value = force_text(option_value)
        if option_value in selected_choices:
            selected_html = mark_safe(' selected="selected"')
            if not self.allow_multiple_selected:
                # Only allow for a single selection.
                selected_choices.remove(option_value)
        else:
            selected_html = ''

        # My custom code to add data-specialty attributes to <option> tags.
        # Get the object to filter upon.
        obj = self.choices.queryset.get(pk=option_value)
        # Get the data field.
        data_field = getattr(obj, 'specialty', False)
        # If the data field has a value set, add it to the return html.
        # Need to check if the data_field has a pk (ie is a ForeignKey field), and handle it appropriately.
        if data_field:
            selected_html += ' data-{0}={1}'.format( 'specialty', str(getattr(data_field, 'pk', data_field)) )

        # This paragraph is copied from django Select.
        return format_html('<option value="{0}" {1}>{2}</option>',
                           option_value,
                           selected_html,
                           force_text(option_label))

但现在我决定我想要单选按钮,而不是选择列表。我的问题是,尝试在单选小部件的渲染器中使用与上述类似的代码失败,因为 self.choices.queryset 没有设置,所以我无法访问我需要的信息。 我怎样才能获得我需要的信息,这是做我想做的最好的方式吗?

我什至修改了核心 django 文件以查看查询集消失的位置。 RadioSelect 是 RendererMixin 的子类。 self.choices.queryset 在其 init、render 和 get_renderer 子功能期间可用? (函数是这个词吗?)。 RadioSelect 的渲染器是 RadioFieldRenderer,它是 ChoiceFieldRenderer 的子类。在它的 init 和渲染中,查询集已经消失(它设置了自己的 self.choices,但即使在 init 中的那一步之前,self.choices 也没有设置)。

【问题讨论】:

    标签: django django-forms django-widget


    【解决方案1】:

    我发现了几种不同的方法来实现我想要的。

    1:编写一个子类 forms.Widget 的自定义小部件。这提供了完全控制,无需尝试“使用”核心类。我使用此链接获取灵感,https://djangosnippets.org/snippets/2589/

    2:修改choices元组(value,label),改成(value,label,object)(例如)。以下链接提供了执行此操作的代码:http://srcmvn.com/blog/2013/01/15/django-advanced-model-choice-field/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 2014-01-11
      • 1970-01-01
      相关资源
      最近更新 更多