我有这种模型:
class Cities(models.Model):
country = models.CharField(max_length=45, blank=True, null=True)
city = models.CharField(max_length=45, blank=True, null=True)
def get_city_name(self):
if self.sub_species:
return str(self.country) + " " + str(self.city)
通过我的模型中的示例数据:
France Paris
France Lyon
France Marseille
Germany Berlin
Germany Bonn
filter_drop_down_menu_city = CityNameForm()
class CityNameChoiceField(forms.ModelChoiceField):
"""
CityNameChoiceField Class
"""
def label_from_instance(self, obj):
"""
This function return the label of the instance
:param obj:
:return:
"""
return obj.get_city_name()
class CityNameForm(forms.Form):
"""
CityNameForm Class
"""
cityName = CityNameChoiceField(
queryset=Cities.objects.order_by('country', 'city'),
empty_label="(ALL Cities)",
help_text="",
required=False,
label='Cities',
)
在我的模板中,我的选择字段呈现之前列出的城市列表。
但是我想要那种选择渲染:
France
France Paris
France Lyon
France Marseille
Germany
Germany Berlin
Germany Bonn
用户也可以选择一个国家(然后我可以选择城市)
答案 0 :(得分:1)
您可以通过更改ModelChoiceField.iterator
进行一些魔术操作,但是该属性未记录在案,使用后果自负。
否则,我认为您需要编写自定义ChoiceField
。
class ModelChoiceIterator(forms.models.ModelChoiceIterator):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.seen = set()
def __iter__(self):
for id, label in super().__iter__():
country = label.split(' ')[0]
if country not in self.seen:
yield (id, country)
self.seen.add(country)
yield (id, label)
class CityNameChoiceField(forms.ModelChoiceField):
iterator = ModelChoiceIterator
def label_from_instance(self, obj):
return obj.get_city_name()
答案 1 :(得分:1)
有一种更简单的方法,只需按照documentation构造选择即可实现所需的目标。祝你好运:)
def cities_as_choices():
choices = []
for country in models.Cities.objects.values('country').distinct():
new_country = []
cities = []
new_country.append(country.get('country'))
for city in models.Cities.objects.filter(country=country.get('country')):
cities.append([city.pk, city.city])
new_country.append(cities)
choices.append(new_country)
return choices
class CityNameForm(forms.Form):
"""
CityNameForm Class
"""
def __init__(self, *args, **kwargs):
super(CityNameForm, self).__init__(*args, **kwargs)
self.fields['cityName'].choices = cities_as_choices()
cityName = forms.ChoiceField(
choices=cities_as_choices(),
help_text="",
required=False,
label='Cities',
)