1. Add a new student. Specify a name ("Alice") and click the Save and
continue editing button.
2. Now click the + to add a Team. Specify a team name ("Team A") and click
the Save button.
3. Back on the student page with the team now selected, click the Save and
continue editing button.
Result: ValidationError
Expected: Student object to be saved and the inline to now be displayed.
{{{#!python
# myapp/models.py
from django.db import models
class Team(models.Model):
name = models.CharField(max_length=255)
def __unicode__(self):
return self.name
class Category(models.Model):
name = models.CharField(max_length=255)
class Student(models.Model):
name = models.CharField(max_length=255)
team = models.ForeignKey(Team, blank=True, null=True)
categories = models.ManyToManyField(Category, through='CategoryInfo')
class CategoryInfo(models.Model):
category = models.ForeignKey(Category)
student = models.ForeignKey(Student)
score = models.CharField(max_length=255)
}}}
{{{#!python
# myapp/admin.py
from django.contrib import admin
from models import Student
from models import Team
class CategoryInlineAdmin(admin.TabularInline):
model = Student.categories.through
class StudentAdmin(admin.ModelAdmin):
inlines = []
def get_inline_instances(self, request, obj=None):
inlines = self.inlines
# Display inline when the object has been saved and a team has
been selected.
if obj and obj.team:
inlines = [CategoryInlineAdmin,]
return [inline(self.model, self.admin_site) for inline in inlines]
class TeamAdmin(admin.ModelAdmin):
pass
admin.site.register(Student, StudentAdmin)
admin.site.register(Team, TeamAdmin)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/25559>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
Comment:
Please see
[https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_inline_instances
the note for get_inline_instances() in the documentation], "If you
override this method, make sure that the returned inlines are instances of
the classes defined in inlines or you might encounter a “Bad Request”
error when adding related objects." You need
`inlines=[CategoryInlineAdmin]` in the class body I believe. If that's
correct, we might amend the docs.
--
Ticket URL: <https://code.djangoproject.com/ticket/25559#comment:1>
* status: new => closed
* resolution: => wontfix
* component: Uncategorized => contrib.admin
Comment:
After looking at this a bit closer, I don't see a way that Django could
generally solve it. Possibly you could fix this in your app by using some
JavaScript to insert the necessary formset HTML fields based on whether or
not a team is selected. Feel free to reopen if you have some ideas or a
patch to share.
--
Ticket URL: <https://code.djangoproject.com/ticket/25559#comment:2>
Comment (by zborboa-google):
Can we document overriding `change_view` is possible to achieve this?
Here's a solution that works. Use `change_view` to conditionally display
the inline. Replace `myapp/admin.py` above with this:
{{{#!python
# myapp/admin.py
from django.contrib import admin
from models import Student
from models import Team
class CategoryInlineAdmin(admin.TabularInline):
model = Student.categories.through
class StudentAdmin(admin.ModelAdmin):
inlines = []
def change_view(self, request, object_id, form_url='',
extra_context=None):
# Display inline when the object has been saved and a team has
been selected.
self.inlines = []
try:
obj = self.model.objects.get(pk=object_id)
except self.model.DoesNotExist:
pass
else:
if obj.team:
self.inlines = [CategoryInlineAdmin,]
return super(StudentAdmin, self).change_view(request, object_id,
form_url, extra_context)
class TeamAdmin(admin.ModelAdmin):
pass
admin.site.register(Student, StudentAdmin)
admin.site.register(Team, TeamAdmin)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/25559#comment:3>
Comment (by timgraham):
I'm not sure that modifying `self.inlines` like that is thread safe.
I don't think documenting every way the admin can be customized has a
place in the Django documentation. It's not trivial to maintain examples
and to ensure they continue working in future versions of Django.
--
Ticket URL: <https://code.djangoproject.com/ticket/25559#comment:4>