Как добавить зависимое поле выбора? (Если в поле 1 выбран определенный выбор, поле 2 исключит его из своих вариантов)

Я пытаюсь создать модель и форму студента, где каждый студент должен иметь 6 предметов, не больше и не меньше. Из этих 6 предметов, 1 предмет из каждой из 3 определенных категорий является обязательным. Например,

Английский Категория: Язык и литература ИЛИ Литература -- МИН 1 НО МАКС 1

Категория языков: Испанский или французский или арабский или мандаринский -- МИН 1 НО МАКС 1

Категория науки: Биология ИЛИ Химия ИЛИ ... -- МИН 1, НЕ МАКС

Для трех других необходимых предметов учащиеся могут выбрать предметы из любой категории Наука, Общество и Искусство (которые присутствуют в choices.py).

Однако я хочу сделать так, чтобы в форме ученики не могли выбрать один и тот же предмет более одного раза. Кроме того, как я могу представить варианты выбора для менее ограничительного поля выбора всех трех различных "категорий" в одном поле выбора?

( Например, 'option1' - это атрибут студента, такой же как 'english', из которого студенты могут выбрать любой вариант из Scienec, Society и Art, но не могут выбрать те же предметы дважды.)

PS: Я пытался найти ответ самостоятельно, читал документацию Django снова и снова и исследовал вопрос, но не нашел ответа. Любая помощь будет очень признательна и поможет мне продвинуться в изучении Django

models.py

from unittest.util import _MAX_LENGTH
from django.db import models
from django.utils.translation import gettext_lazy as _
from students.choices import *

# Create your models here.


class Student(models.Model):
    student_number = models.PositiveIntegerField()
    first_name = models.CharField(max_length=50) #Attribute containing student's first name, cannot exceed 50 characters
    last_name = models.CharField(max_length=50) #Attribute containing student's last name, cannot exceed 50 characters
    email = models.EmailField(max_length=100) #Attribute containing student's email, cannot exceed 100 characters
    
    #Subjects
    english = models.CharField(max_length=2, choices=English.choices, null=True, blank=False)
    math = models.CharField(max_length=2, choices=Math.choices, null=True, blank=False)
    language = models.CharField(max_length=1, choices=Language.choices, null=True, blank=False)
    science = models.CharField(max_length=4, choices=Science.choices, null=True, blank=False)


#How I thought of doing it


  #  option1 = models.CharField(max_length=4, choices=Science.choices+Art.choices+Science.choices)
 #   def validate_unique_subject(subject):
  #      if subject.value == 'science.value':         # value is the second term in the tuple 
   #         raise ValidationError(
   #             _('Student cannot pcik the same subject twice')
   #         )




    #language: french, spanish, arabic, mandarin  --> manadtory, 1 max
    #english: ll, l --> mandatory, 1 max
    #math: aa, ai   --> mandatory, 1 max

    #sciences: cs, biology, chemistry, physics, ess, psychology, political science
    #arts
    #individuals and societies
    



    def __str__(self):
        return f'{self.first_name} {self.last_name}'

forms.py

from random import choices
from django import forms
from .models import Student
from students.choices import *

class StudentForm(forms.ModelForm):
    
    english = forms.ChoiceField(choices=English.choices)
    science = forms.ChoiceField(choices=Science.choices)
    language = forms.ChoiceField(choices=Language.choices)
    math = forms.ChoiceField(choices=Math.choices)

    class Meta:
        model = Student
        fields = '__all__'      #imports all of Student model's fields
        labels = {
            'student_number': 'Student Number',    #changes how the attribute names are presented to the user
            'first_name': 'First Name',
            'last_name': 'Last Name',                       
            'email': 'Email',
            'english': 'English',
            'math': 'Math',
            'language': 'Language',
            'science': 'Science',
        }
        widgets = {
            'student_number': forms.NumberInput(attrs={'class': 'form-control'}),
            'first_name': forms.TextInput(attrs={'class': 'form-control'}),
            'last_name': forms.TextInput(attrs={'class': 'form-control'}),                     
            'email': forms.EmailInput(attrs={'class': 'form-control'}),
        }

choices.py

from unittest.util import _MAX_LENGTH
from django.db import models
from django.utils.translation import gettext_lazy as _


class English(models.TextChoices):
    LANGLIT = 'LL', _('Language and literature')
    LIT = 'L', _('Literature')
    

class Math(models.TextChoices):
    AA = 'AA', _('Analysis & Approaches')
    AI = 'AI', _('Analysis & Interpretation')


class Language(models.TextChoices):
    FRENCH = 'F', _('French')
    SPANISH = 'S', _('Spanish')
    ARABIC = 'A', _('Arabic')
    MANDARIN = 'M', _('Mandarin')


class Science(models.TextChoices):
    BIOLOGY = 'BIO', _('Biology')
    CHEMISTRY = 'CHEM', _('Chemistry')
    PHYSICS = 'PHY', _('Physics')
    COMPUTERSCIENCE = 'CS', _('Computer Science')
    DESIGNTECHNOLOGY = 'DT', _('Design Technology')
    ESS = 'ESS', _('Environmental Systems and Societies')


class Society(models.TextChoices):
    MANAGEMENT = 'BM', _('Business Management')
    ECONOMICS = 'ECON', _('Economics')
    GEOGRAPHY = 'GEO', _('Geography')
    GLOBALPOLITICS = 'GP', _('Global Politics')
    HISTORY = 'HIS', _('History')
    PSYCHOLOGY = 'PSYCH', _('Psychology')

class Art(models.TextChoices):
    VISUALARTS = 'VA', _('Visual Arts')
    MUSIC = 'MUS', _('Music'),
    FILM = 'FILM', _('Film')


Вернуться на верх