ModelChoiceField optgroupタグでどのように設定できますか?
これは例です:
models.py
class Link(models.Model):
config = models.ForeignKey(Config)
name = models.URLField(u'Name', null=True, max_length=50)
gateway = models.IPAddressField(u'Gateway', null=True)
weight = models.IntegerField(u'Weight', null=True)
description = models.TextField(u'Description', blank=True)
def __unicode__(self):
return self.name
forms.py
class LinkForm(ModelForm):
config = ModelChoiceField(queryset=Config.objects.all(), empty_label="Choose a link",widget=GroupedSelect())
class Meta:
model = Link
ChoiceFieldを次のようにレンダリングしたいと思います。
example.html
<select id="id_config" name="config">
<option selected="selected" value="">Choose a link</option>
<optgroup label="Configuration" >
<option value="8">Address: 192.168.1.202/255.255.255.0 </option>
<option value="9">Address: 192.168.1.240/255.255.255.0 </option>
<option value="10">Address: 192.168.3.1/255.255.255.0 </option>
</optgroup>
</select>
** UPDATE **
class GroupedSelect(Select):
def render(self, name, value, attrs=None, choices=()):
if value is None: value = ''
final_attrs = self.build_attrs(attrs, name=name)
output = [format_html('<select{0}>', flatatt(final_attrs))]
for index, option_gp in enumerate(self.choices):
if index == 0:
option_value = smart_unicode(option_gp[0])
option_label = smart_unicode(option_gp[1])
output.append(u'<option value="%s">%s</option>' % (escape(option_value), escape(option_label)))
output.append('<optgroup label = "Configuration">')
Elif index!=0 and index <= len(self.choices):
option_value = smart_unicode(option_gp[0])
option_label = smart_unicode(option_gp[1])
output.append(u'<option value="%s">%s</option>' % (escape(option_value), escape(option_label)))
output.append(u'</optgroup>')
output.append(u'</select>')
return mark_safe('\n'.join(output))
カスタムフィールドを作成する必要はありません。Djangoは既にジョブを実行しています。適切な形式の選択肢を渡すだけです。
MEDIA_CHOICES = (
('Audio', (
('vinyl', 'Vinyl'),
('cd', 'CD'),
)
),
('Video', (
('vhs', 'VHS Tape'),
('dvd', 'DVD'),
)
),
)
Django-categories で使用する@Stefan Manastirliu回答の拡張。 (欠点は、以下のget_tree_data()
関数では1レベルしか許可されないことです)。 bootstrap multiselect のようなJavaScriptプラグインと組み合わせると、次のような複数選択を取得できます
Models.py
from categories.models import CategoryBase
class SampleCategory(CategoryBase):
class Meta:
verbose_name_plural = 'sample categories'
class SampleProfile(models.Model):
categories = models.ManyToManyField('myapp.SampleCategory')
forms.py
from myapp.models import SampleCategory
def get_tree_data():
def rectree(toplevel):
children_list_of_tuples = list()
if toplevel.children.active():
for child in toplevel.children.active():
children_list_of_tuples.append(Tuple((child.id,child.name)))
return children_list_of_tuples
data = list()
t = SampleCategory.objects.filter(active=True).filter(level=0)
for toplevel in t:
childrens = rectree(toplevel)
data.append(
Tuple(
(
toplevel.name,
Tuple(
childrens
)
)
)
)
return Tuple(data)
class SampleProfileForm(forms.ModelForm):
categories = forms.MultipleChoiceField(choices=get_tree_data())
class Meta:
model = SampleProfile
ここに良いスニペットがあります:
オプションフィールドとオプションフィールドと選択ウィジェットの選択: http://djangosnippets.org/snippets/200/