Установите атрибут на основе другого атрибута

#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