Как запросить базу данных в Django формах? - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть модель:

class Registration(models.Model):
    student_name = models.CharField(max_length=50)
    season = models.ForeignKey(Season, on_delete=models.CASCADE)
    subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
    address = models.TextField()

    class Meta:
        unique_together = (('student_name', 'selected_season', 'selected_subject'),)

Я хочу создать форму для этой модели, где пользователю будет предоставлена ​​возможность выбрать subject на основе выбранного им season. У меня также есть модели для них:

class Subject(models.Model):
    subject_name = models.CharField(max_length=50)
    ...

class Season(models.Model):
    season = models.CharField(max_length=2, primary_key=True)
    subject = models.ManyToManyField(Subject)
    ...

Я не знаю, как запросить форму. Это должен быть ModelForm или обычная форма? Как запросить базу данных в форме?

1 Ответ

1 голос
/ 23 апреля 2020

Вы можете знать, какой сезон был выбран при отправке формы, поэтому простого способа реализовать это не существует (обратите внимание, что это ограничение HTTP, а не django). IOW вам понадобится либо процесс "мастера", либо сценарии внешнего интерфейса.

Решение "мастера" состоит в следующем: одна первая форма, где пользователь выбирает сезон, пользователь отправляет форму, ваш код выбирает связанный субъектов и отображает вторую форму с выбором субъектов, пользователь выбирает темы и отправляет для окончательной проверки (примечание: обычно это делается в одном представлении, используя скрытое поле формы, чтобы отслеживать текущий этап и какой сезон был выбран на первом этапе ). Это гарантированно работает (если правильно реализовано, конечно, xD), но не очень удобно для пользователя.

Второе решение - использовать интерфейсные сценарии.

В простейшей форме, когда пользователь выбирает сезон, вы используете js, чтобы скрыть объекты других сезонов (или вы сначала скрываете все объекты и отображаете только соответствующие, когда сезон выбран). Это можно сделать довольно просто, сгруппировав все предметы для данного сезона в одном и том же наборе полей (или любом другом теге контейнера) с идентификатором, совпадающим с идентификатором сезона, или с помощью отдельного html «выбора» (с тем же именем, но другим идентификаторы) за сезон. Конечно, вы также можете иметь все предметы в одном html выборе (или как угодно), сохранять лицевую (js) карту сезонов => предметов и обновлять свой выбор или что-либо еще из этого отображения.

Это решение можно заставить работать (в «ухудшенном» режиме) без JS (вам просто нужно убедиться, что селектор (ы) объектов по умолчанию видимы и активны). Вам нужно будет реализовать пользовательскую внутреннюю сторону проверки (для этого формы cf django делают c), чтобы убедиться, что субъект так или иначе совпадает с сезоном ( never , доверяйте проверке с внешней стороны, это только удобный сахар), поэтому в худшем случае форма не будет проверена.

Теперь, если у вас есть много сезонов и тем, вы можете предпочесть выполнить запрос ajax, когда пользователь выбирает сезон и заполняет селектор тем из результата этого запроса (чтобы избежать первоначального рендеринга список опций), но тогда вы не сможете заставить его работать без JS (зависит от того, является ли это проблемой или нет, зависит от ваших требований).

РЕДАКТИРОВАТЬ

Если я следую опции мастера форм, мне нужно создать 2 формы, первая из которых состоит только из сезона.

Что ж, вы можете сделать это с помощью одной формы (передавая аргумент, чтобы указать, что должно быть сделано), но на самом деле использовать две формы гораздо проще.

2-я форма будет состоять из остальных вариантов (кроме сезонов), я прав? Так должна ли вторая форма быть моделью?

Ну, в этом суть моделей, не так ли?

Как поместить набор запросов в ModelChoiceField в модели? Я гуглил, но ничего не смог найти -

В __init__ вашей формы вы обновляете self.fields["subject"].queryset с вашим фильтрованным набором запросов.

ВАЖНО : НЕ ПЫТАЙТЕСЬ коснуться self.fieldname - это определение поля на уровне класса, поэтому его изменение может привести к совершенно неожиданным результатам в производстве (уже здесь, это и так) было довольно весело отлаживать xD).

Теперь, как говорится, для вашего случая использования, я считаю, вам будет лучше с простым js фильтрующим решением - его проще всего настроить - на бэкэнде он полностью прозрачен, а на передней - Конечная часть довольно проста с использованием jQuery - она ​​намного удобнее и гарантированно работает.

...