標準の 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())