Django ModelAdmin 更改表单输入的特定查询集

Specific Queryset for Input on Django ModelAdmin Change Form

我有一个 'Registration' 对象,用户可以在前端毫无问题地创建它。

看起来像这样:

class Registration(models.Model):
    person = models.ForeignKey(Person, on_delete=models.PROTECT)
    course_detail = models.ForeignKey(CourseDetail, on_delete=models.PROTECT)
    camp_shirt = models.ForeignKey(CampShirt, on_delete=models.PROTECT)
    comments = models.CharField(max_length=200, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return "%s" % (self.course_detail.course.camp)

当我在管理员中单击给定的注册时 - 加载需要一段时间,因为有成千上万的 Person 对象。

为了便于使用 - 我们永远不会需要编辑与给定注册关联的 'person',所以我想让 'person' 下拉列表只显示从 Django 管理员编辑时在人员查询集中选择的用户。

因此,当我转到 http://myapp.com/admin/registration/23/change 时,我希望表单仅将当前选定的人显示为下拉列表中的唯一选项。

我的管理模型如下所示:

class RegistrationAdmin(admin.ModelAdmin):
    list_display = ("person", "course_detail")

    class Meta:
        # I think this is what I do in order to override the default admin form? Not sure.
        form = RegistrationAdminForm

我的 RegistrationAdminForm 如下所示:

class RegistrationAdminForm(forms.ModelForm):
    # course_detail, person, camp_shirt, comments
    person = forms.ModelChoiceField(queryset=Person.objects.filter(
        id=registration.person.id)
    )

    def __init__(self, registration, *args, **kwargs):
        super(RegistrationAdminForm, self).__init__(*args, **kwargs)
        self.fields['person'].queryset = Person.objects.filter(
            id=registration.person.id
        )

    class Meta:
        model = Registration
        fields = '__all__'

主要问题:如何更改管理表单以便为 django 管理中的某个字段返回特定的查询集?

如果人员字段永远不会更改,您可以将人员字段添加到 readonly_fields,将不会呈现包含所有 Person 个对象的 select。

class RegistrationAdmin(admin.ModelAdmin):
    list_display = ("person", "course_detail")
    readonly_fields = ("person", )

那么您就不需要您的自定义表单了。仅供参考,当您想将自定义表单添加到 ModelAdmin 时,您不要将其放在 Meta 中,而是在表单本身

中定义它
class MyModelAdmin(admin.ModelAdmin):
    form = MyModelForm