Django TabularInline through relationship

Let’s say I have the following models:

class A(models.Model):
  pass

class B(models.Model):
  a = models.ForeignKey("A")

class C(models.Model):
  b = models.ForeignKey("B")

I can have a TabularInline widget showing all Bs of a particular A like this:

class AAdmin(admin.ModelAdmin):
  inlines = [BInline]

class BInline(admin.TabularInline):
  model = B

How can I have a TabularInline widget showing all Cs of a particular A? (all Cs of all Bs of a particular A)

I guess I’m looking for something like:

class AAmin(admin.ModelAdmin):
  inlines = [CInline]

class CInline(admin.TabularInline):
  model = C.through.B

Note: I know about the existence of django-nested-admin. this package will show all Cs grouped by every Bs, which is not what I want. I want to show only Cs, without any references to Bs.

From a relational model, that doesn’t really make sense, especially in the admin. How can you relate a C to an A in the absence of a B? (I’m more thinking of trying to add a new C.)
(And if this is something being presented to a non-administrative user, why are you using the admin?)

Having said the above, you could probably achieve what you want by writing a custom admin form to display that list of related C.

It makes perfect sense for my use case. Model A is a bus line. Model B is a bus stop (a bus line has multiple bus stops). Model C is a physical object belonging to a bus stop.

I want to show all physical objects of bus line X. I don’t really need to edit or add new physical objects, only show the existing ones.

Then create your template and view to do this. That way you have complete control over what’s being displayed on the page, and you’re not fighting the admin to do it. If you’re not performing any edits or additions, this isn’t even a form.

This brings the issue down to the more common list view / detail view type of application, where the list view is the list of bus lines and the detail view is the list of physical objects. (Assuming you’d want to select the bus line from a list.)

I know… I was hoping there would be a way to avoid having to create all those files. I mean, if I want a view-only that can be easily represented with a “through” relation in the ORM model, why can’t django render a TabularInline-readonly widget with the data?

Because the admin isn’t designed nor intended to be an end-user reporting tool. You’re trying to use a screwdriver to drive nails.

In all fairness, TabularInlines already can be read-only (via de readonly attribute). And Django can already give me, easily, all Cs from a given A using the ORM.

It seems fair enough to ask Django’s admin to combine those two things, and I’m fairly sure that this could actually be achieved with a small patch on Django’s side.

Excerpt from the official Django admin site documentation:

<quote from the docs>
The admin’s recommended use is limited to an organization’s internal management tool. It’s not intended for building your entire front end around.

The admin has many hooks for customization, but beware of trying to use those hooks exclusively. If you need to provide a more process-centric interface that abstracts away the implementation details of database tables and fields, then it’s probably time to write your own views.
<end of quote - emphasis mine>

If you wish to use the admin facility in this way, you already have the ability to define a custom form for the admin - you can make the admin display whatever you’d like. (Heaven knows, I’ve done it enough times myself in ways I’d rather not admit.)

And, if you feel that strongly about it, you can always file a ticket / submit a patch. (You probably should check the current set of tickets to see if this topic has already been discussed.) But as it is contrary to my understanding of the purpose of the admin, my opinion would be that it doesn’t belong there.