说我有以下型号......
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()
我还对表格有一个额外的限制,即副队长必须具有与队长相同的专长。我已经在表单干净等中实现了检查,但希望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)。
答案 0 :(得分:4)
我发现了一些不同的方法来实现我想要的目标。
1:编写一个子类Forms.Widget的自定义小部件。这样可以完全控制,不会尝试“使用”核心类。我使用此链接获取灵感,https://djangosnippets.org/snippets/2589/
2:修改选项元组(value,label)
,并将其更改为(value,label,object)
(例如)。以下链接提供了执行此操作的代码:http://srcmvn.com/blog/2013/01/15/django-advanced-model-choice-field/