встроенный выбор «один ко многим» с администратором django - PullRequest
49 голосов
/ 17 мая 2011

У меня настроены стандартные отношения многие-к-одному.Есть несколько полей, но для наших целей здесь уместна соответствующая модель:

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

Я создал администратора, и он отлично работает.у меня даже автоматически есть возможность установить класс, когда я редактирую студента.Однако, когда я иду, чтобы создать / редактировать класс, все, что я получаю, это поле ввода имени.

Есть ли способ добавить поле / поле, где студенты могут быть добавлены как члены класса изСтраница администратора класса?Я могу сделать форму встроенной, но это для создания новых студентов.У меня уже созданы все мои ученики, и я просто ищу быстрый способ добавить несколько существующих учеников в другой класс ».

Ответы [ 2 ]

37 голосов
/ 17 мая 2011

Есть! Вы хотите InlineModelAdmin (см. Документацию InlineModelAdmin здесь)

Пример кода вкратце:

class StudentAdminInline(admin.TabularInline):
    model = Student

class ClassAdmin(admin.ModelAdmin):
    inlines = (StudentAdminInline, )
admin.site.register(Class, ClassAdmin)
35 голосов
/ 11 января 2012

Вот решение "пользовательской формы", как предложил Люк Снерингер. В любом случае, я удивлен отсутствием готового решения 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
...