Django Form - условное отображение полей с помощью JQuery
Отказ от претензий: Я зашел в тупик. Попробовав 10+ различных вопросов и ответов только на Stack Overflow, я уперся в стену. Я надеюсь, что смогу решить эту проблему с помощью прямого вопроса. Пожалуйста, будьте мягче. Я потратил несколько дней на поиск в Stack Overflow и в Интернете, чтобы попытаться заставить это работать. Есть МНОГО предложений, и ни одно из них не сработало для меня до сих пор. Признаюсь, я не очень хорошо разбираюсь в JS, и, вероятно, поэтому я сильно спотыкаюсь на этом требовании.
Если у вас есть замечания по качеству этого вопроса, пожалуйста, прокомментируйте его с конструктивной критикой. Просто сказать, что вопрос плохо сформулирован, не поможет. Однако, если вы поделитесь конкретными примерами того, что я мог бы сделать, чтобы сформулировать вопрос более полезным образом, это будет здорово. Надеюсь, вы сможете убедиться, что я приложил немало усилий, чтобы изложить суть желаемой цели, а также то, что я пытался сделать.
В данной реализации используется Django 4.0 и Bootstrap5 с CrispyForms.
Цель: Пользователь, выбирая значение в одном поле, определяет, будет ли показано или скрыто другое поле. По умолчанию условное поле имеет значение "Нет". Воздействующее поле будет показано, когда пользователь изменит условное поле на значение "Да". В частности, если пользователь выберет "Да" для поля Повторяющееся событие, будет показано поле Шаблон повторения.
Обратите внимание, что реализация Class Based Views в шаблоне работает отлично. Вот скриншот формы (с неработающим требованием условного поля):

Существующий код (только соответствующие фрагменты)
Вот что у меня есть в models.py:
YES_NO_CHOICES = [
('No', 'No'),
('Yes', 'Yes'),
]
RECURRENCE_PATTERN_CHOICES = [
('---', '---'),
('Daily', 'Daily'),
('Weekly', 'Weekly'),
('Monthly', 'Monthly'),
('Yearly', 'Yearly'),
]
class Event(models.Model):
event_name = models.CharField(
max_length=70,
help_text='''Enter a name for the event. This is a required field and is limited to 70 characters.'''
)
recurring_event = models.CharField(
max_length=5,
choices=YES_NO_CHOICES,
default='No',
help_text='''Is this a one off event or will it recur? Selecting Yes will open up additional fields.'''
)
recurrence_pattern = models.CharField(
max_length=10,
choices=RECURRENCE_PATTERN_CHOICES,
default='---',
help_text='''Select the recurrence pattern for this event.'''
)
Вот что у меня есть в файле forms.py:
class EventStaffSummaryUpdateView(UpdateView):
"""Event Staff Update view - allows staff to change event details"""
model = Event
template_name = 'events/event_staff_summary_form.html'
fields = [
'event_name',
'recurring_event',
'recurrence_pattern',
]
context_object_name = 'event'
В шаблоне event_staff_summary.html (с использованием наследования) у меня есть:
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<div id="event_name">
{{ form.event_name|as_crispy_field }}
</div>
<div id="recurring_event">
{{ form.recurring_event|as_crispy_field }}
</div>
<div id="recurrence_pattern">
{{ form.recurrence_pattern|as_crispy_field }}
</div>
</fieldset>
<div class="form-group pt-4 pb-2">
{% if page_type == 'Update' %}
<button class="btn btn-BlueGray" type="submit">Update Event</button>
{% else %}
<button class="btn btn-BlueGray" type="submit">Create Event</button>
{% endif %}
</div>
</form>
</div>
В шаблоне base.html я использую ссылку Google JQuery (найденную на моем пути как простой способ внедрения JQuery):
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
Как вы можете видеть на скриншоте, сама форма отображается отлично. Таким образом, модели, форма и даже html работают до сих пор. Представление на основе класса обновления работает с БД. Осталось только показать или скрыть шаблон Recurrence на основе значения в поле Recurrence event. Что приводит меня к...
Что я уже пробовал?
Из 10+ JS сниппетов, которые я встречал и пробовал, вот ведущий кандидат, который кажется наиболее близким. Я очень хочу, чтобы это работало, так как это имеет смысл для меня.
<script>
$("#recurring_event").change(function() {
if ($(this).val() === "Yes") {
$('#recurrence_pattern').show();
} else {
$('#recurrence_pattern').hide();
}
});
</script>
Request
У кого-нибудь есть предложения о том, как я могу заставить это работать? У меня есть требования к ряду условно отображаемых полей. Я бы предпочел не работать с чекбоксами, так как обычно клиент предпочитает, чтобы пользователь явно нажимал "Да" или "Нет", поскольку это для них более понятно (они считают, что при закрытом вопросе и выборе "да/нет" нет возможности двусмысленности)
Это требование условных полей в формах реализовано во многих случаях, поэтому я знаю, что не ищу невозможного. Я надеюсь, что существует простая доработка (или очистка) сниппета javascript, который я разместил. Я также приветствую другие предложенные JS сниппеты
Заранее спасибо за помощь.
Обновить библиотеку до
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
Заверните функцию в событие готовности DOM.
Обновите селектор на <select> (из div). Сделайте это, просмотрев DOM.
Конечный результат:
(function($){
$(document).ready(function(){
$("#id_recurring_event").change(function() {
if ($(this).val() === "Yes") {
$('#id_recurrence_pattern').show();
} else {
$('#id_recurrence_pattern').hide();
}
});
})
})(jQuery);
Для этого можно использовать метод trigger(). Таким образом, всякий раз, когда ваша страница загружается, вызывайте этот метод, чтобы выполнить событие изменения, которое прикреплено к select-box .
Рабочий код :
$(document).ready(function() {
$("#id_recurring_event").change(function() {
if ($(this).val() === "No") {
$('#recurrence_pattern').hide();
} else {
$('#recurrence_pattern').show();
}
});
$("#id_recurring_event").trigger("change")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="content-section">
<form method="POST">
<fieldset class="form-group">
<div id="event_name">
ABC ..
</div>
<div id="recurring_event">
<select id="id_recurring_event">
<option value="Yes">Yes</option>
<option value="No" selected="true">No</option>
</select>
</div>
<div id="recurrence_pattern">
somethings ..................
</div>
</fieldset>
</form>
</div>