one-to-many inline select with django admin
There is! You want InlineModelAdmin
(see InlineModelAdmin documentation here)
Sample code in brief:
class StudentAdminInline(admin.TabularInline):
model = Student
class ClassAdmin(admin.ModelAdmin):
inlines = (StudentAdminInline, )
admin.site.register(Class, ClassAdmin)
Probably, this will help:
I used the described approach, but changed methods save
and save_m2m
in the following way:
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_m2m(self):
pass
def save(self, *args, **kwargs):
self.fields['bars'].initial.update(foo=None)
foo_instance = Foo()
foo_instance.pk = self.instance.pk
# Copy all other fields.
# ... #
foo_instance.save()
self.cleaned_data['bars'].update(foo=instance)
return instance
class FooAdmin(admin.ModelAdmin):
form = FooForm
Here is "custom form" solution as Luke Sneeringer suggested. Anyway, I'm suprised by absence of out-of-the-box Django solution to this (rather natural and probably common) problem. Am I missing something?
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