Один-ко-многим встроенный выбор с 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
Я создал администратора, и он отлично работает. он даже автоматически имеет возможность установить класс, когда я редактирую Студент. Однако, когда я иду для создания/редактирования класса, все, что я получаю, является полем ввода для имени.
Есть ли способ добавить поле/поле, в котором учащиеся могут быть добавлены в качестве членов класса со страницы администратора класса? Я могу сделать форму встроенной, но это нужно для создания новых учеников. У меня уже есть все мои ученики, и я просто ищу быстрый способ добавления нескольких существующих учеников в разные классы.
Ответы
Ответ 1
Вот решение "пользовательской формы", как предложил Люк Снейрингер. Во всяком случае, я удивлен отсутствием готового решения 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
Ответ 2
Есть! Вы хотите InlineModelAdmin
(см. Документацию InlineModelAdmin)
Краткое описание кода:
class StudentAdminInline(admin.TabularInline):
model = Student
class ClassAdmin(admin.ModelAdmin):
inlines = (StudentAdminInline, )
admin.site.register(Class, ClassAdmin)
Ответ 3
Вы также можете запустить имена учеников через вторую модель, чтобы они были ForeignKey
. Например, после оригинальной записи кода добавьте:
class AssignedStudents(models.Model):
assigned_to = models.ForeignKey(Class, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
Затем добавьте строчку к администратору, как сказал Люк Снерингер. Вы получите выпадающий список, из которого вы можете выбрать имена учеников. Хотя есть возможность создавать новых учеников.