How to group the choices in a Django Select widget?

前端 未结 3 1416
挽巷
挽巷 2020-12-13 10:18

Is it possible to created named choice groups in a Django select (dropdown) widget, when that widget is on a form that is auto-generated from a data Model?

3条回答
  •  情话喂你
    2020-12-13 10:44

    Here's what worked for me, not extending any of the current django classes:

    I have a list of types of organism, given the different Kingdoms as the optgroup. In a form OrganismForm, you can select the organism from a drop-down select box, and they are ordered by the optgroup of the Kingdom, and then all of the organisms from that kingdom. Like so:

      [----------------|V]
      |Plantae         |
      |  Angiosperm    |
      |  Conifer       |
      |Animalia        |
      |  Mammal        |
      |  Amphibian     |
      |  Marsupial     |
      |Fungi           |
      |  Zygomycota    |
      |  Ascomycota    |
      |  Basidiomycota |
      |  Deuteromycota |
      |...             |
      |________________|
    

    models.py

    from django.models import Model
    
    class Kingdom(Model):
        name = models.CharField(max_length=16)
    
    class Organism(Model):
        kingdom = models.ForeignKeyField(Kingdom)
        name = models.CharField(max_length=64)
    

    forms.py:

    from models import Kingdom, Organism
    
    class OrganismForm(forms.ModelForm):
        organism = forms.ModelChoiceField(
            queryset=Organism.objects.all().order_by('kingdom__name', 'name')
        )
        class Meta:
            model = Organism
    

    views.py:

    from models import Organism, Kingdom
    from forms import OrganismForm
    form = OrganismForm()
    form.fields['organism'].choices = list()
    
    # Now loop the kingdoms, to get all organisms in each.
    for k in Kingdom.objects.all():
        # Append the tuple of OptGroup Name, Organism.
        form.fields['organism'].choices = form.fields['organism'].choices.append(
            (
                k.name, # First tuple part is the optgroup name/label
                list( # Second tuple part is a list of tuples for each option.
                    (o.id, o.name) for o in Organism.objects.filter(kingdom=k).order_by('name')
                    # Each option itself is a tuple of id and name for the label.
                )
            )
        )
    

提交回复
热议问题