使用django admin进行一对多内联选择

MrG*_*ass 52 python django django-models django-admin

我有一个标准的多对一关系设置.有很多字段,但就我们的目的而言,相关模型是:

class Class(models.Model):
    name = models.CharField(max_length=128)

class Student(models.Model):
    class = models.ForeignKey(Class)
    name = models.CharField(max_length=128)
    address = models.CharField(max_length=128)
    # ...etc
Run Code Online (Sandbox Code Playgroud)

我创建了一个管理员,它运行得很好.在我编辑学生时,它甚至可以自动设置班级.但是,当我去创建/编辑一个类时,我得到的只是名称的输入框.

有没有办法添加一个框/字段,可以从Class管理页面添加学生作为Class的成员?我可以在线创建一个表单,但那就是创建新的学生.我已经创建了所有学生,我只是在寻找一种快速方法,将多个现有学生添加到不同的班级.

Luk*_*ger 38

有!你想要的InlineModelAdmin (参见InlineModelAdmin文档)

示例代码简介:

class StudentAdminInline(admin.TabularInline):
    model = Student

class ClassAdmin(admin.ModelAdmin):
    inlines = (StudentAdminInline, )
admin.site.register(Class, ClassAdmin)
Run Code Online (Sandbox Code Playgroud)

  • 尝试实施,这不是我需要的.正如我在问题中所说,我知道如何添加内联表单,但TabularInline旨在创建一个新的Object.我想简单地允许用户从现有的学生列表中进行选择. (13认同)
  • 顺便说一下,在命名模型类"Class"时要非常小心.它确实有效,但它会在以后咬你(例如,在`Student`的第一行).而且,`class = models.ForeignKey(Class)`*不会*工作,因为"class"是一个保留字. (3认同)
  • 这显然没有回答问题!它正在寻找一种快速方法将多个现有学生添加到不同的班级......同样,现有的不是创建新的...... (2认同)

zag*_*zag 35

这是Luke Sneeringer建议的"自定义形式"解决方案.无论如何,我对没有开箱即用的Django解决方案(相当自然且可能是常见的)问题感到惊讶.我错过了什么吗?

from django import forms
from django.db import models
from django.contrib import admin

class Foo(models.Model):
    pass

class Bar(models.Model):
    foo = models.ForeignKey(Foo)

class FooForm(forms.ModelForm):
    class Meta:
        model = Foo

    bars = forms.ModelMultipleChoiceField(queryset=Bar.objects.all())

    def __init__(self, *args, **kwargs):
        super(FooForm, self).__init__(*args, **kwargs)
        if self.instance:
            self.fields['bars'].initial = self.instance.bar_set.all()

    def save(self, *args, **kwargs):
        # FIXME: 'commit' argument is not handled
        # TODO: Wrap reassignments into transaction
        # NOTE: Previously assigned Foos are silently reset
        instance = super(FooForm, self).save(commit=False)
        self.fields['bars'].initial.update(foo=None)
        self.cleaned_data['bars'].update(foo=instance)
        return instance

class FooAdmin(admin.ModelAdmin):
    form = FooForm
Run Code Online (Sandbox Code Playgroud)

  • 两年过去了,这仍然是我能找到的唯一解决方案 - 除非您知道任何新的发展?请问:self.fields ['bars']行的目的是什么.initial.update(foo = None)? (4认同)
  • 为了与ModelForm API保持一致,foo_form.save(commit = False)应该返回一个尚未保存到数据库的对象(请参阅https://docs.djangoproject.com/en/dev/topics/forms/modelforms /#的保存方法); hovewer提供的实现忽略了'commit'参数.很可能你不会使用commit = False; 如果是的话,没有问题. (2认同)
  • @zag,有一件事我无法理解——模型保存在这段代码中的哪里?`instance = super(FooForm, self).save(commit=False)` 不会将实例提交到数据库。在函数 `instance.save()` 的其余部分中,没有调用...我凭经验(在我的项目中)看到这是有效的,但我看不出如何:)你能帮助我理解这一点吗? (2认同)
  • @zag 你好!现在才 2018 年,这是我发现的最相关且实际上只有部分功能的代码段,这很可悲。但是,当我尝试保存 Foo 对象时。它给了我错误:未保存的模型实例<Foo>不能用于 ORM 查询,有什么想法吗? (2认同)