简体   繁体   中英

In Django, remove options in a choice-field dropdown based on the value selected in other field in a model

I'm new to Django and any help is appreciated, How can I restrict the choice option in one field based on a previous field. For example, if I select 'dog' for animal, I want to remove 'chocolate' from the FOOD_CHOICE. Thank you!!!

ANIMAL_CHOICE = (
     ('a','cat'),
     ('b','dog'),
     ('c','fish'),
)
FOOD_CHOICE = (
      ('a', 'chocolate'),
      ('b', 'kittySnack'),
      ('c', 'steak'),
)

class Animal(models.Model):
    animal = models.CharField(max_length=1, choices= ANIMAL_CHOICE)
    food   = models.CharField(max_length=1, choices= FOOD_CHOICE)

As explained here , you should do the validation on the model form or in the model clean method and raise a ValidationError there.

Here is an example, in which you could override the clean method of your model's form :

forms.py

class AnimalForm(ModelForm):
    class Meta:
        model = Animal
        fields = "__all__"

    def clean(self):
        cleaned_data = super(AnimalForm, self).clean()
        animal = self.cleaned_data.get("animal")
        food = self.cleaned_data.get("food")
        if animal == "b" and food == "a": # Might not work, but this is the general idea
            raise forms.ValidationError("Chocolate can't be selected with Dogs")

NB: At the line where I commented that it might not work, you'll have to debug a bit. I don't remember (and I can't test right now) if the cleaned_data returns a tuple or the actual value, or the humand-readable value.

Now, I guess that you want your select in your HTML to dynamically change. For the frontend, you'll need to do a bit of JavaScript. There are many ways on how to do it with JS, but here is one:

(in your template, between <script> tags)

var selectAnimal = document.getElementById("select-animal");
var selectFood = document.getElementById("select-food");

selectAnimal.addEventListener("change", function() {
    if(this.value == "a")
    {
        
        // remove from select the "chocolate" option
        for (var i=0; i<selectFood.length; i++) {
            if (selectFood.options[i].text == 'chocolate')
                selectFood.remove(i);
        }
    }
    else {
        
        // checking if "chocolate" is in select or not
        let has_chocolate = false;
        for (var i=0; i<selectFood.options.length; i++){
            if (selectFood.options[i].text == "chocolate"){
                has_chocolate = true;
            }
        }
        
        if (!has_chocolate){ // if "chocolate" is missing
            option = document.createElement("option");
            option.text = "chocolate";
            option.value = "a";
            selectFood.add(option);
        }
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM