Я пытаюсь продублировать функциональность этого созданного вручную <select>
, используя правильную форму Django.
{% regroup roll_counts by get_type_display as roll_list %}
<select name="film">
<option>Select a film</option>
{% for type in roll_list %}
<optgroup label="{{ type.grouper }}">
{% for film in type.list %}
<option value="{{film.id}}">{{ film.manufacturer }} {{ film.name }} ({{ film.count }})</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
Набор запросов для roll_counts
выглядит следующим образом:
roll_counts = Film.objects\
.filter(roll__owner=owner, roll__status='storage')\
.filter(format=camera.format)\
.annotate(count=Count('name'))\
.order_by('type')
Я пытаюсь воссоздать это, используя своего рода Django ModelForm
, чтобы иметь возможность фактически проверить данные, отправленные в форму. Конечная цель состоит в том, чтобы иметь возможность «загрузить» камеру рулоном пленки. То есть: связать Roll
(с внешним ключом для Film
) с конкретным Camera
и пометить указанную камеру в состоянии loaded
. Таким образом, <select>
отображает данные, которые не обновляются формой. Что нужно изменить, так это модели Roll
и Camera
, а не модель Film
. Но я предположил, что все, что может быть обработано в представлении, которое получает данные из формы.
Я не уверен, как заставить ModelForm
отображать вышеупомянутый запрос roll_count
(и вложенный / optgroup
<select>
), поскольку он не относится к одному полю в этой модели Film
.
Есть идеи, как поступить?
Обновление:
Принятый ответ позволил решить вложенную часть головоломки, но другая часть - получение данных, передаваемых из вида в форму и QuerySet для полевой работы.
В представлении вы можете передать все, что хотите, экземпляру формы:
form = LoadCameraForm(owner=owner, format=camera.format)
В форму я добавил пользовательский __init__
(обратите внимание на owner, format
между *args
и **kwargs
):
def __init__(self, *args, owner, format, **kwargs):
super().__init__(*args, **kwargs)
self.fields['roll_counts'].queryset = Film.objects\
.filter(roll__owner=owner, roll__status='storage')\
.filter(format=format)\
.annotate(count=Count('name'))\
.order_by('type')
(я до сих пор не уверен, как сделать так, чтобы мои аннотированные count
появлялись.)
Затем, чтобы сложить все части, запись поля в форме выглядит так:
roll_counts = GroupedModelChoiceField(\
label='Pick a film to load',\
queryset=None,\
group_by_field='type')