web-dev-qa-db-ja.com

Django adminを使用した1対多のインライン選択

標準的な多対1の関係が設定されています。たくさんのフィールドがありますが、ここでの目的のために、関連するモデルは次のとおりです。

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

管理者を作成しましたが、うまく機能します。生徒を編集しているときに自動的にクラスを設定することもできます。ただし、クラスを作成/編集する場合、名前の入力ボックスのみが表示されます。

クラス管理ページからクラスのメンバーとして生徒を追加できるボックス/フィールドを追加する方法はありますか?フォームをインラインで作成できますが、それは新しい生徒を作成することです。私はすでにすべての生徒を作成しており、複数の既存の生徒を異なるクラスに追加する簡単な方法を探しています。

49
MrGlass

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
35
zag

有る! InlineModelAdmin(InlineModelAdminのドキュメントを参照)

簡単なサンプルコード:

class StudentAdminInline(admin.TabularInline):
    model = Student

class ClassAdmin(admin.ModelAdmin):
    inlines = (StudentAdminInline, )
admin.site.register(Class, ClassAdmin)
37
Luke Sneeringer

また、2番目のモデルで学生名を実行して、ForeignKeyにすることもできます。たとえば、元のコードポストの追加後:

... class AssignedStudents(models.Model): assigned_to = models.ForeignKey( Class, on_delete=models.CASCADE ) student = models.ForeignKey( Student, on_delete=models.CASCADE )

次に、Luke Sneeringerが言ったように、管理者にインラインを追加します。生徒名を選択できるドロップダウンリストが表示されます。ただし、新しい学生を作成するオプションはまだあります。

0
Kris O