2

我有一个自定义 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())
4

3 回答 3

3

self.choices.queryset.all()应该管用。

于 2013-04-30T15:31:31.870 回答
2

最后我决定我不需要访问查询集本身,所以我只是使用 self.choices 而不是 self.choices.queryset(并删除默认情况下由 modelchoicefields 放入的空白选项)。

这解决了我眼前的问题,但我仍然想知道为什么 self.choices.queryset 的行为与 self.choices 不同。不清楚是错误还是我不理解的功能。

于 2013-02-04T10:58:28.693 回答
1

我认为问题出在渲染模板或查询集的缓存中。但我建议不要处理这个问题,而是使用一个很棒的包:django-crispy-forms,它允许您使用 django 的模板引擎自定义任何字段。经过无数次尝试在 django 中自定义小部件渲染后,这是我能找到的最佳解决方案,结果证明也是一个相当简单的解决方案。

于 2014-08-29T13:32:08.400 回答