14

可以说我有一个模型School和另一个模型Student

class Student(models.Model):
   school = models.ForeignKey(School)
   name = models.CharField(max_length=100)

在管理员中单击学校时,会出现一个新页面,显示学校模型字段和值。

我还想在该页面本身中选择已经可用的学生列表。

内联是不同的,它们将允许创建和编辑属于该学校的新记录(学生)。但我不希望这样,让我们​​假设已经有很多学生记录可用。我应该能够从该学校模型页面的管理员中选择它们。

4

4 回答 4

12
class SchoolAdminForm(forms.ModelForm):
    students = forms.ModelMultipleChoiceField(
        queryset=Student.objects.all(),
        widget=FilteredSelectMultiple(verbose_name='students', is_stacked=False))

    class Meta:
        model = School
        fields = ['your_school_fields_go_here']

    def __init__(self, *args, **kwargs):
        super(SchoolAdminForm, self).__init__(*args, **kwargs)
        if self.instance:
            # fill initial related values
            self.fields['students'].initial = self.instance.student_set.all()

class SchoolAdmin(admin.ModelAdmin):
   form = SchoolAdminForm

   def save_model(self, request, obj, form, change):
       super().save_model(request, obj, form, change)
       original_students = set(obj.student_set.values_list("id", flat=True))
       current_students = set(map(lambda x: x.id, form.cleaned_data['students']))
       if original_students != current_students:
           add_to_school = current_students - original_students
           Student.objects.filter(id__in=add_to_school).update(school_id=obj.id)
           remove_from_school = original_students - current_students
           Student.objects.filter(id__in=remove_from_school).update(school_id=None)
于 2017-02-21T18:13:47.607 回答
1

我按照菲利克斯的建议做了。唯一的问题是它给出了这样的错误:

ValueError: Unsaved model instance <School: disscount_None> cannot be used in an ORM query.

我发现的原因是在保存当前 School 模型之前,您无法更改学生对象中的外键。因为还没有任何东西可以添加到 fk 属性中!所以使用 felix 解决方案,但在 save_model 函数中使用“for”之前的 obj.save()

   def save_model(self, request, obj, form, change):
       original_students = obj.student_set.all()
       new_students = form.cleaned_data['students']
       remove_qs = original_students.exclude(id__in=new_students.values('id'))
       add_qs = new_students.exclude(id__in=original_students.values('id'))


       obj.save()   

       for item in remove_qs:
               obj.student_set.remove(item)
       for item in add_qs:
               obj.student_set.add(item)
           
于 2020-11-06T16:35:44.837 回答
0

您的意思是对于给定的School实例,您希望能够获得与该学校相关的所有学生的列表吗?

在这种情况下,您使用related_name您指定的 ForeignKey 关系的属性。你还没有定义你在related_name哪里做:

school = models.ForeignKey(School)

很好,它只使用默认的相关名称,即子类(学生)的名称,后跟 _set

所以对于你的学校实例:

school = School.objects.get(pk=1)
students = school.student_set.all()  # or .filter() or .exclude() etc

然后您可以将该学生查询集传递到您的模板中。

于 2013-08-29T08:09:02.490 回答
0

您可以禁用内联“添加”权限。请参阅InlineModelAdmin

于 2013-08-29T10:21:59.513 回答