我在Django 1.6.5上有以下模型
class Location(models.Model):
parent = models.ForeignKey('Location', blank=True, null=True)
name = models.CharField(max_length=50)
class Meta:
db_table = 'locations'
ordering = ('parent__name', 'name')
def __unicode__(self, ):
if self.parent!= None:
return self.name + " (" + self.parent.name + ")"
else:
return self.name
我在下拉列表中列出了这些位置,因此我想显示名称+(如果可用,则为parent.name)
任何想法都可以做到这一点,而无需拨打数千个电话?
答案 0 :(得分:1)
最后我这样做了:
在forms.py中我创建了一个方法:
def get_locations_with_parents():
location_list = [(0,'Select One ...')]
locations = Position.objects.raw('select l.id, l.name, p.name as parent from locations l left join locations p on l.parent_id = p.id order by parent, l.name')
for l in locations:
if l.parent:
location = (int(l.id), l.name + " (" + l.parent + ")")
else:
location = (int(l.id), l.name)
location_list.append(location)
return tuple(location_list)
然后以我使用的形式 locations = forms.ChoiceField(choices = get_locations_with_parents(),validators = [validate_empty])
它可以解决问题,它不再对数据库进行2000次查询。有一些验证器和清洁等......但与解决方案并不真正相关。
答案 1 :(得分:0)
我可能误解了你的问题,但我认为我有类似的情况。在下拉列表中,您希望使用location
的名称标记对象。如果该位置有parent
,您希望在位置名称后面的括号内显示该父级的名称。
您可以通过覆盖ModelForm的__init__
方法来完成此任务:
def __init__(self, *args, **kwargs):
def new_label_from_instance(self, obj):
try:
#see if there is a parent or not
p = obj.parent
except:
#no parent; use the location's default label
rep = obj.description
return rep
#if we find a location's parent, p=parent label and d=location label
d = obj.description
rep = "%s (%s)" % (d, p)
return rep
super(PublisherCreateTSCForm, self).__init__(*args, **kwargs)
funcType = type(self.fields['location'].label_from_instance)
self.fields['location'].label_from_instance = funcType(new_label_from_instance, self.fields['location'], forms.models.ChoiceField)
在你这样做之前,你应该知道这样做的后果。看看这个老问题:
Django CheckboxSelectMultiple override 'choices' from ModelForm
此处与label_from_instance
相关的文档(链接部分的底部):https://docs.djangoproject.com/en/1.7/ref/forms/fields/#modelchoicefield