Ответ 1
Проблема заключается не в том, чтобы иметь встроенные линии; это с пути ModelForm
работает, в общем. Они только создают поля формы для реальных полей в модели, а не связанные атрибуты менеджера. Однако вы можете добавить эту функциональность в форму:
from django.contrib.admin.widgets import FilteredSelectMultiple
class ProjectAdminForm(forms.ModelForm):
class Meta:
model = Project
userprofiles = forms.ModelMultipleChoiceField(
queryset=UserProfile.objects.all(),
required=False,
widget=FilteredSelectMultiple(
verbose_name='User Profiles',
is_stacked=False
)
)
def __init__(self, *args, **kwargs):
super(ProjectAdminForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.fields['userprofiles'].initial = self.instance.userprofile_set.all()
def save(self, commit=True):
project = super(ProjectAdminForm, self).save(commit=False)
if commit:
project.save()
if project.pk:
project.userprofile_set = self.cleaned_data['userprofiles']
self.save_m2m()
return project
class ProjectAdmin(admin.ModelAdmin):
form = ProjectAdminForm
...
Небольшое пошаговое руководство, вероятно, по порядку. Сначала мы определяем поле формы userprofiles
. Он будет использовать ModelMultipleChoiceField
, который по умолчанию приведет к множественному выбору. Поскольку это не является фактическим полем на модели, мы не можем просто добавить его в filter_horizontal
, поэтому вместо этого мы просто попросим использовать тот же виджетов FilteredSelectMultiple
, который он будет использовать, если он был указан в filter_horizontal
.
Мы первоначально установили набор запросов как весь набор UserProfile
, вы не можете его фильтровать здесь, но на этом этапе определения класса форма не была создана и, следовательно, не имеет ее instance
установлен еще. В результате мы переопределяем __init__
, чтобы мы могли установить отфильтрованный запрос в качестве начального значения поля.
Наконец, мы переопределим метод save
, чтобы мы могли установить связанное содержимое менеджера так же, как и данные в формате POST, и все готово.