#django #django-models
Вопрос:
Как выбрать хостел в зависимости от пола?
Глобальные переменные
BOYS_HOSTEL_CHOICES = (…)
GIRLS_HOSTEL_CHOICES = (…)
class Student(models.Model):
MALE = 'M'
FEMALE = 'F'
#...
GENDER_CHOICES = (
(MALE, 'Male'),
(FEMALE, 'Female')
)
gender = models.CharField(
max_length = 10,
choices = GENDER_CHOICES,
verbose_name="gender",
)
hostel = models.CharField(
max_length=40,
choices = BOYS_HOSTEL_CHOICES if gender == 'M' # <---
else GIRLS_HOSTEL_CHOICES,
default = 'some hostel'
)
Ответ №1:
Вы не можете сделать это на уровне модели, если только не хотите реализовать это как ограничение базы данных. Но это звучит так, как будто вы просто хотите ограничить выбор формы.
Разрешите оба варианта в модели:
hostel = models.CharField(
max_length=40,
# Combine choices
choices=BOYS_HOSTEL_CHOICES GIRLS_HOSTEL_CHOICES,
default='some hostel'
)
Вы также можете использовать проверку модели Django для проверки ограничения на сохранение в Python.
Если вам нужно ограничить выбор в отображаемой форме, форма должна знать значение gender
поля и затем может ограничить выбор в hostel
поле.
from django import forms
class StudentForm(forms.ModelForm):
# ...
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['hostel'].choices = BOYS_HOSTEL_CHOICES
Ответ №2:
Если вы не знаете надмножество вариантов выбора, то вам не следует устанавливать атрибут выбора в модели, потому что модель django проверяет выбор полей.
Сделайте поле «хостел» атрибутом «Поле без выбора».
hostel = models.CharField(max_length=40)
В этом случае вы можете создать форму или форму модели, в которой вы можете задать динамический выбор.
from django import forms
class StudentForm(forms.ModelForm):
default_choices = [your default choices if you want]
hostel = forms.CharField(max_length=40, choices = default_choices)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['hostel'].choices = self.get_dynamic_choice()
def get_dynamic_choice(self):
''' you can set choices BOYS_HOSTEL_CHOICES or GIRLS_HOSTEL_CHOICES'''
return choices
но если вы хотите, чтобы выпадающее меню зависело от выбора поля пола, вы меняете значение выбора, то вы можете реализовать это с помощью вызова javascript или Ajax
Редактировать:
Если вы не хотите писать код javascript или ajax, вы можете использовать пакет django-автозаполнение-light.
вы перенаправляете выбранное значение пола в поле общежитие и получаете доступ в представлении, где вы можете задать динамические параметры для поля формы общежитие. Вы также можете выполнить поиск по значению поля хостел. Этот пакет также поддерживает набор запросов.
В forms.py,
from django import forms
class StudentForm(forms.ModelForm):
default_choices = [your default choices if you want]
hostel = forms.ChoiceField(max_length=40,
choices = default_choices,
widget=autocomplete.ListSelect2(url='hostel_autocomplete', forward=['gender'],))
В urls.py,
urlpatterns = [
path('hostel_autocomplete/', HostelAutocompleteView.as_view(), name='hostel_autocomplete'),
]
В views.py,
from dal import autocomplete
class HostelAutocompleteView(autocomplete.Select2ListView):
def get_list(self):
if not self.request.user.is_authenticated:
return []
# you get select gender value
gender = self.forwarded.get('gender', None)
if gender == 'M':
# your BOYS_HOSTEL_CHOICE_LIST
choice_list = ['A hostel','B hostel']
elif gender == 'F':
# your GIRL_HOSTEL_CHOICE_LIST
choice_list = ['C hostel', 'D hostel']
else:
choice_list = []
return choice_list
ссылка на документы с прямым значением — https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#filtering-results-based-on-the-value-of-other-fields-in-the-form