2

標準の ModelChoiceField ウィジェットを置き換えるカスタム django ウィジェットがあります。

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 クエリセットが正常に読み込まれるため、初期化方法を理解していないと思います。そのモデルの新しいインスタンスを追加してページをリロードすると、クエリセットは更新されず、新しいインスタンスが含まれます。また、新しいインスタンスをリストに表示するには、サーバーを再起動する必要があります。クエリセットが一度だけ初期化され、更新されない理由はありますか?

編集:追加するには、フォームからウィジェットを削除してデフォルトのウィジェットを使用すると(どちらが正しいかわからない)、それが問題なく動作し、期待どおりに動作するため、それがウィジェットコードであると確信しています。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.queryset ではなく、self.choices を使用しています (そして、modelchoicefields によってデフォルトで挿入される空白の選択肢を削除します)。

これで当面の問題は解決しましたが、self.choices.queryset が self.choices と異なる動作をする理由を知りたいと思います。それがバグなのか、私が理解していない機能なのかは不明です。

于 2013-02-04T10:58:28.693 に答える
1

レンダリングされたテンプレートまたはクエリセットのキャッシュのどこかに問題があると思います。しかし、それに対処する代わりに、django のテンプレート エンジンを使用して任意のフィールドをカスタマイズできるdjango-crispy-formsという優れたパッケージを使用することをお勧めします。django でウィジェットのレンダリングをカスタマイズしようと何度も試みた結果、これが私が見つけた最良の解決策であり、非常に単純な解決策であることが判明しました。

于 2014-08-29T13:32:08.400 に答える