I'm building a simple Q&A website with Django 1.8
.
I want to create select optgroup based on foreing key (details below).
How can I do that?
College
class College(models.Model):
title = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
slug = models.SlugField(blank=True, max_length=100)
university = models.ForeignKey(to=University, related_name='college_list')
University
class University(models.Model):
title = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
slug = models.SlugField(unique=True, blank=True, max_length=100)
Question
class Question(models.Model):
title = models.CharField(max_length=150)
body = RedactorField(verbose_name=u'Vsebina')
slug = models.SlugField(unique=True, blank=True, max_length=100)
college = models.ForeignKey(to=College, default=1, related_name='questions')
QuestionForm
class CreateQuestionForm(ModelForm):
class Meta:
model = Question
fields = ['title', 'body', 'college']
Template (displaying the select)
{{ form.college }}
Current result
Needed result
Thanks!
I know this is old, but I have hit upon a solution to this problem of "displaying ModelChoiceField options categorised by a ForeignKey to another model".
Django added the ability to provide nested optgroups in a ChoiceField a few years back. However there is no automatic way to build nested choices like this from a queryset of nested model instanes.
I managed to solve it using OrderedDict to organise the subgroups into groups, then set the choices to the .items() generator. It's important to realise that you're dealing with dynamic choices here as the University and College model instances could change over time.
QuestionForm:
from collections import OrderedDict
from django.core.exceptions import ObjectDoesNotExist
class CreateQuestionForm(ModelForm):
"""
ModelForm which dynamically builds a nested set of choices for University and College
"""
class Meta:
model = Question
fields = ['title', 'body', 'college']
def __init__(self, *args, **kwargs):
super(CreateQuestionForm, self).__init__(*args, **kwargs) # Sets up the fields
university_college_choices_dict = OrderedDict() # Abused to sort into groups
for college in self.fields["college"].queryset.order_by("university__title", "college__title"):
choice_tuple = (college.pk, college.title)
try:
university_name = college.university.title
except (AttributeError, ObjectDoesNotExist):
university_name = False # Ends up in the generic ungrouped bin
try:
university_college_choices_dict[university_name].append(choice_tuple)
except KeyError:
university_college_choices_dict[university_name] = [choice_tuple]
self.fields["college"].choices = university_college_choices_dict.items() # MUST call .items() to extract the nested tuples
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With