Django - Динамическое добавление второй формы на страницу
Я ищу руководство по созданию динамической формы в Django, которая меняется в зависимости от того, какие участники находятся на встрече.
Предыстория такова: Приложение используется для отслеживания результатов встреч нескольких команд, каждая из которых состоит из 4-8 человек. В течение нескольких дней команда может провести 6 встреч. Для каждого собрания команда выбирает 1 или 2 членов в качестве участников собрания. На каждом собрании команда выдвигает участников таким образом, чтобы за время тренинга все члены команды приняли участие в одном или нескольких собраниях. На каждом собрании все остальные члены команды являются "Наблюдателями".
Проблема, с которой я столкнулся, заключается в том, как динамически вставить форму или поля формы для каждого из наблюдателей, учитывая, что количество наблюдателей может быть любым - от одного до 6. Идея заключается в том, чтобы позволить наблюдателям "оценивать" собрание и записывать этот результат в модель наблюдателя.
Представление ScoreCreate правильно устанавливает 1-го участника и заполняет выпадающий список "Другой участник" всеми остальными членами команды.
HTMX в шаблоне передает данные 1-го и, если выбран "другой участник", функции наблюдателей, которая затем разбирается, кто должен быть наблюдателем.
Я не могу понять, как создать и вставить форму, которая предварительно заполняется каждым из наблюдателей и позволяет ввести оценку (Имя наблюдателя, поле: рейтинг), учитывая, что количество наблюдателей будет варьироваться в зависимости от количества членов команды и наличия или отсутствия двух участников в собрании.
Мысли о том, как я могу подойти к этому, приветствуются.
МОДЕЛИ:
from .choices import SCORE_CHOICES, RATING_CHOICES
class Meeting(models.Model)
date = models.DateTimeField(auto_now=True)
class Team(models.Model):
# up to 8 members per team
name = model.CharField(max_length=25)
class Participant(models.Model):
name = model.CharField(max_length=25)
team = model.ForeignKey(Team, on_delete.models.CASCADE)
class Score(models.Model):
# primary is required, secondary is not required
meeting = models.ForeignKey('Meeting', on_delete.models.CASCADE)
primary_participant = models.ForeignKey('Participant', on_delete.models.CASCADE)
secondary_participant = models.ForeignKey('Participant', related_name='secondary_participant', on_delete.model.CASCADE, blank=True, null=True)
score = models.CharField(max_length=25, choices = SCORE_CHOICES)
class Observer(models.Model):
score = models.ForeignKey(Score, on_delete.models.CASCADE)
observer = models.ForeignKey(Participant, on_delete.models.CASCADE)
rating = models.CharField(max_length=1, choices=RATING_CHOICES)
ПРОСМОТРОВ:
class ScoreCreate(LoginRequiredMixin, CreateView):
model = Score
form_class = ScoreCreateForm
template_name = 'score_create.html'
def get_initial(self):
participants = Participant.objects.filter(slug=self.kwargs['slug'])
participant_id = self.kwargs['pk']
other_participants = participants.filter(~Q(pk=self.kwargs['pk'])
def observers(request):
participant = request.GET.get('participant')
other_participant = request.GET.get('other_participant')
team = request.GET.get('team')
if other_participant:
observers = Participant.objects.filter(~Q(id=participant) & ~Q(id=other_participant) & Q(team=team))
else:
observers = Participant.objects.filter(~Q(id=participant) & Q(team=team) & Q(role='PARTICIPANT'))
return render(request, 'trial/partials/all_observers.html', context={'observers': observers})
TEMPLATE: score.html
<form method="POST" name="score_participants">
<div class="d-flex">
<div class="align-self-end g-color-primary text-uppercase g-letter-spacing-1 g-font-weight-800 g-my-10">Meeting Details
</div>
<div class="ml-auto">
<input class="btn btn-md btn-warning g-mr-10 g-mb-15 g-rounded-50" onclick="location.href='#'" type="button"
value="Cancel">
<button class="btn btn-md u-btn-primary g-mr-0 g-mb-15 g-rounded-50" type="submit">Submit</button>
</div>
</div>
<div class="d-flex g-mt-0 g-brd-top g-brd-gray-light-v3 g-bg-secondary">
<div class="g-mt-12 g-ml-10">Participant:</div>
<div>
{{form.participant|as_crispy_field}}
</div>
<div class="ml-auto g-mt-13 g-mb-12 g-mr-10 g-color-primary text-uppercase g-letter-spacing-1 g-font-weight-600">{{participant}}</div>
</div>
<div class="d-flex g-mt-0 g-brd-top g-brd-gray-light-v3">
<div class="g-mt-18 g-ml-10 g-mr-50">Meeting Number:</div>
<div class="ml-auto g-mt-13 g-mr-10">{{form.meeting_number|as_crispy_field}}</div>
<div class="d-flex g-mt-0 g-brd-top g-brd-gray-light-v3 g-bg-secondary">
<div class="g-mt-18 g-ml-10 g-mr-50">Name of other meeting participant:</div>
<div class="ml-auto g-mt-13 g-mr-10"
hx-get="{% url 'observers' %}"
hx-include="[name='score_participants']"
hx-trigger="change"
hx-target = "#observers">
{{form.other_participant|as_crispy_field}}
</div>
</div>
<div class="g-mt-0 g-brd-top g-brd-gray-light-v3">
<div id="observers"></div>
</div>
...
TEMPLATE: observer.html
{% block content %}
{% for observer in observers %}
<div class="d-flex">
<div>{{observer}}</div>
<div class="ml-auto">RATING (RADIO BUTTONS)</div>
</div>
{% endfor %}
{% endblock %}
Идея заключается в том, чтобы использовать представление, которое обрабатывает данные, поступающие с той страницы, которую вы показали, переходя на следующую страницу, которая показывает формы. Так что если вы просто пытаетесь показать формы на следующей странице, вы можете обрабатывать логику внутри вашего представления и сказать, что если есть 4 наблюдателя, то вы хотите иметь цикл for, который создает форму для каждого из них и добавляет их в список. Затем в HTMX вы можете для каждого из этого списка вывести эту форму, и вы можете использовать идентификаторы для каждого html объекта в forms.py и управлять ими в css.
Если вы хотите сохранить эту модель для последующего использования. По сути, вы хотите сделать то же самое, но вместо передачи этих значений по URL (управление параметрами в представлении) вы можете просто использовать их прямо из базы данных. На самом деле, это просто работает в любой ситуации с той небольшой оговоркой, что использование большего количества обращений к базе данных замедлит работу сайта.