问题
I have a custom django widget to replace the standard ModelChoiceField widget.
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)
The issue appears to be around this area:
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()
the self.choices.queryset line should get the queryset that was passed to the ModelChoiceField, and I think I lack an understanding of how it is initialised, because when I load up the page for the first time the Model queryset populates fine, however if I add a new instance of that model and reload the page, the queryset doesn't update to include the new instance. And I have to restart the server in order to get the new instance to appear in the list. Is there any reason as to why the queryset would only be initialised once and never updated?
Edit: To add, I'm convinced it's the widget code because when I remove the widget from the form and use the default widget (not sure which that is) it works flawlessly and as I would expect it to. I just can't work out why the model_queryset variable is never updating with the new queryset.
the form code that relates to this widget in my project is literally just:
address = forms.ModelChoiceField(queryset=models.Address.objects.all(),
widget=widgets.SelectModelWidget())
回答1:
self.choices.queryset.all()
should work.
回答2:
In the end I decided that I did not need access to the queryset itself, so rather than self.choices.queryset, I am just using self.choices (and removing the blank choice that is put in by default by modelchoicefields).
That solved my immediate problem but I would still be interested to know why self.choices.queryset behaves differently to self.choices. Whether it's a bug or a feature I do not understand is unclear.
回答3:
I think problem is somewhere in caching of a rendered template or a queryset. But instead of dealing with that, I would recommend, using a great package: django-crispy-forms, which allows you to customize any field using django's templating engine. After numerous attempts trying to customize widgets rendering in django, that was the best solution I could find, turned out to be a fairly simple one too.
来源:https://stackoverflow.com/questions/14672407/django-widget-queryset-not-updating