我有一个ModelForm,它使用CheckboxSelectMultiple小部件来表示来自ManyToManyField的数据 . 默认情况下,这将呈现一个复选框列表,其标签设置为相关模型的 __str__
方法的返回值 . 但是,除了窗口小部件提供的choice_label之外,我还希望显示相关模型中其他字段的数据 . 例如,考虑以下实现:
models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Item(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey('Category', on_delete=models.CASCADE)
def __str__(self):
return self.name
class Order(models.Model):
items = models.ManyToManyField('Item')
forms.py
from django import forms
from .models import Order
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['items']
widgets = {'items': forms.widgets.CheckboxSelectMultiple}
template.html
{% for item in form.items %}
<tr>
<td>{{ item.tag }}</td>
<td>{{ item.choice_label }}</td>
<td>{{ item.category }}</td>
</tr>
{% endfor %}
这里的问题是template.html的 {{ item.category }}
部分 . 使用 {% for item in form.items %}
循环遍历所有项目复选框时, item
的类型为 BoundWidget
,而不是 Item
. 这就是提供 tag
和 choice_label
属性以呈现表单的复选框 . 我的问题是 BoundWidget
似乎没有任何关于复选框所代表的 Item
实例的引用,这将允许我访问任何其他模型数据,例如项目所在的类别 . 有什么方法可以解决这个问题吗?
编辑:
我能想到的唯一方法是:
templatetags / app_tags.py
from django import template
from models import Item
register = template.Library()
@register.inclusion_tag('app/order_item_table.html')
def show_item_table(items):
item_objs = []
for item in items:
id = item.data['value']
obj = Item.objects.get(id=id)
item_objs.append((item, obj))
return {'items': item_objs}
order_item_template.html
{% for item, obj in items %}
<tr>
<td>{{ item.tag }}</td>
<td>{{ item.choice_label }}</td>
<td>{{ obj.category }}</td>
</tr>
{% endfor %}
template.html
{% load app_tags %}
{% show_item_table form.items %}
但这看起来令人难以置信的hacky,我真的想知道是否有更好的方法来做到这一点?
1 回答
我发现了一个不同的解决方案(我必须重新实现一个小部件供我自己使用)
我也改变了撕裂,在你的情况下
get_context
ovverridign可能就足够了)注意
get_context
如何使用self.qs
更新上下文现在,
form
self.fields['my_field'].queryset = qs
我需要它来过滤可能的选项,你需要的是self.fields['data_controller'].widget.qs = qs
在视图中(我使用基于类的视图)
现在在窗口小部件模板(html文件)中,您可以访问
qs
对象我做过滤器的地方
{% with obj_item=qs|index:widget.index %}
@register.filter def index(List, i): return List[int(i)]
在你的情况下,它应该
{% with obj_item=qs|index:item.index %}
(不确定项目是否有index
希望它的帮助