Django管理员通过HTML< SELECT>愉快地支持多对一和多对多关系。表单字段,允许分别选择一个或多个选项。甚至还有一个很好的Javascript filter_horizontal
小部件可以提供帮助。
我正试图通过related_name从一对多方面做同样的事情。我不知道它与多对多有什么不同,只要在表单中显示它,我只需要一个多选SELECT列表。但我不能简单地将related_name
值添加到我的ModelAdmin
派生字段列表中。
Django是否以这种方式支持一对多字段?
我的Django模型是这样的(为简化示例而设计):
class Person(models.Model):
...
manager = models.ForeignKey('self', related_name='staff',
null=True, blank=True, )
在人员管理页面中,我可以轻松获得< SELECT>列表显示所有可能的工作人员从中选择此人员的经理。我还想显示一个多选< SELECT>所有经理的员工名单。
我不想使用内联,因为我不想编辑下属的详细信息;我想要能够从列表中添加/删除人员。
(我正在尝试使用django-ajax-selects替换SELECT小部件,但这是旁边的。)
答案 0 :(得分:4)
ManyToManyField的解决方案: http://code.djangoproject.com/ticket/13369#comment:2
答案 1 :(得分:1)
您可以在表单的 init 方法中设置初始值。
将它们称为self.fields ['manager_staff']。initial。
像这样:
class PersonAdminForm(forms.ModelForm):
manager_staff = forms.ModelMultipleChoiceField(
queryset=Person.objects.all(),
required=False,
)
def __init__(self, *args, **kwargs):
super(PersonAdminForm, self).__init__(*args, **kwargs)
if self.instance.id is not None:
selected_items = [ values[0] for values in Person.objects.filter(
#whatever your filter criteria is
) ]
self.fields['manager_staff'].initial = selected_items
答案 2 :(得分:0)
这可能最终成为其中一个限制。这就是我设法提出的。可以创建自定义表单并将其传递给管理站点以用于呈现页面。但是,我无法得到的是正确显示初始值。也许在Forms上更好的人可以使用一些我不了解的超级秘密元API并解决这个问题。
class Person(models.Model):
# ...
manager = models.ForeignKey('self', related_name='staff', null=True, blank=True)
def manager_staff(self):
return self.manager.staff.all()
class PersonAdminForm(forms.ModelForm):
manager_staff = forms.ModelMultipleChoiceField(
initial='manager_staff', # Can't get this to work
queryset=Person.objects.all(),
required=False,
)
class Meta:
model = Person
class PersonAdmin(admin.ModelAdmin):
form = PersonAdminForm
def save_model(self, request, obj, form, change):
for id in form.data.getlist('manager_staff'):
# This is kind of a weak way to do this, but you get the idea...
p = Person.objects.get(id=id)
p.manager = obj.manager
p.save()
super(PersonAdmin, self).save_model(request, obj, form, change)
admin.site.register(Person, PersonAdmin)
答案 3 :(得分:0)
这是我根据T. Stone和nicoechaniz的答案提出的。初始数据的提供方式与nicoechaniz提供的方式大致相同。为了节省,您必须小心处理全新Person的情况以及编辑现有Person。这就是使save()
方法复杂化的原因,具体取决于ModelForm API的非公开部分。真的,这应该建立在Django中。我想这是一个常见的特色。
class PersonAdminForm(forms.ModelForm):
staff = forms.ModelMultipleChoiceField(
queryset=Person.objects.all(),
required=False,
)
class Meta:
model = Person
def __init__(self, *args, **kwargs):
super(PersonAdminForm, self).__init__(*args,**kwargs)
if self.instance.pk is not None:
self.initial['staff'] = [values[0] for values in self.instance.staff.values_list('pk')]
def save(self, commit=True):
instance = super(PersonAdminForm, self).save(commit)
def save_m2m():
instance.staff = self.cleaned_data['staff']
if commit:
save_m2m()
elif hasattr(self, 'save_m2m'):
save_old_m2m = self.save_m2m
def save_both():
save_old_m2m()
save_m2m()
self.save_m2m = save_both
else:
self.save_m2m = save_m2m
return instance
save.alters_data = True
class PersonAdmin(admin.ModelAdmin):
form = PersonAdminForm