Форма Django со связанными данными из двух других таблиц, отображаемыми с использованием вложенной (optgroup) <select> - PullRequest
0 голосов
/ 09 мая 2018

Я пытаюсь продублировать функциональность этого созданного вручную <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')

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Я сделал это один раз! Смотрите мой фрагмент здесь :) https://djangosnippets.org/snippets/10573/

0 голосов
/ 09 мая 2018

Нет встроенного поля формы, которое может делать то, что вы хотите, поэтому вам придется создать собственное поле и виджет для отображения поля в HTML. Взгляните на модуль django.forms.fields, и вы увидите, как определяются поля формы. Хотя для некоторых это может быть проблемой, чтобы понять это правильно.

Если честно, я бы порекомендовал поискать другой вариант для отображения вашей формы. У вас может быть поле выбора для type, а при выборе вы можете загрузить опции для film, используя ajax?

Только мои 2 цента:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...