我有一个自定义的django小部件来替换标准的ModelChoiceField小部件。
class SelectModelWidget(forms.TextInput):
"""
@Usage: field = ModelChoiceField(queryset=Model.objects.all(),
widget=SelectModelWidget(attrs={}))
"""
def __init__(self, attrs=None, title=None,
template="widgets/select_widget.html"):
super(SelectModelWidget, self).__init__(attrs)
self.template = template
self.title = title
def render(self, name, value, attrs=None):
if value is None: value = ''
# TODO: the queryset does not update
# Set the title for the selection page, use model name as default
model_queryset = self.choices.queryset
if model_queryset is not None and self.title is None:
self.title = model_queryset.model._meta.verbose_name.title()
# Get the currently selected instance if it exists
try:
instance = model_queryset.get(pk=value)
text = instance
except (ValueError, model_queryset.model.DoesNotExist):
text = ''
form_id = attrs.pop("id")
widget_template = loader.get_template(self.template)
context = Context({
"attrs": attrs,
"id": form_id,
"name": name,
"value": value,
"text": text,
"title": self.title,
"queryset": model_queryset,
})
return widget_template.render(context)
这个问题似乎围绕着这个领域:
model_queryset = self.choices.queryset
if model_queryset is not None and self.title is None:
self.title = model_queryset.model._meta.verbose_name.title()
self.choices.queryset行应该获取传递给ModelChoiceField的查询集,我认为我对它是如何初始化缺乏了解,因为当我第一次加载页面时,模型查询集填充得很好但是,如果我添加该模型的新实例并重新加载页面,则查询集不会更新以包含新实例。我必须重新启动服务器才能使新实例出现在列表中。是否有任何理由为什么查询集只会被初始化一次并且永远不会更新?
编辑:要添加,我确信它是小部件代码,因为当我从表单中删除小部件并使用默认小部件(不确定是哪个)时,它可以完美地工作,正如我所期望的那样。我无法弄清楚为什么model_queryset变量永远不会使用新的查询集进行更新。
在我的项目中与此窗口小部件相关的表单代码实际上只是:
address = forms.ModelChoiceField(queryset=models.Address.objects.all(),
widget=widgets.SelectModelWidget())
答案 0 :(得分:3)
self.choices.queryset.all()
应该有用。
答案 1 :(得分:2)
最后我决定我不需要访问查询集本身,所以我只使用self.choices(并删除默认情况下由modelchoicefields放入的空白选项)而不是self.choices.queryset。
这解决了我的直接问题,但我仍然有兴趣知道为什么self.choices.queryset与self.choices的行为不同。不知道它是一个我不理解的错误或功能还不清楚。
答案 2 :(得分:1)
我认为问题是在缓存渲染模板或查询集的某个地方。但是,我建议使用一个很棒的包django-crispy-forms,而不是处理它,它允许你使用django的模板引擎自定义任何字段。经过多次尝试在django中尝试自定义窗口小部件渲染后,这是我能找到的最佳解决方案,结果也是一个相当简单的解决方案。