Question

How can I create a Django TabularInline with a link to the detail view?

Answer and Explanation

To create a Django TabularInline with a link to the detail view, you need to customize the TabularInline template. Here's how you can achieve this:

1. Understand Django's TabularInline:

- A TabularInline is used in the Django admin to display related objects in a tabular format directly within the parent object's change form. By default, it doesn't provide links to the detail view of the related objects.

2. Override the `TabularInline` Template:

- Django allows you to override default admin templates. You can create a custom template for your TabularInline to add the desired links.

3. Create a Custom `TabularInline` Class:

- Define a custom TabularInline class that sets your custom template.

4. Example Code:

First, let's define your models. Suppose you have a `Parent` model and a related `Child` model:

# models.py
from django.db import models

class Parent(models.Model):
   name = models.CharField(max_length=200)

class Child(models.Model):
   parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='children')
   name = models.CharField(max_length=200)

Next, create a custom template called admin/edit_inline/tabular.html in your app's template directory, the one that contains the app `templates` directory in the same folder with `models.py`:

{% raw %} {# admin/edit_inline/tabular.html #}
{% extends "admin/edit_inline/tabular.html" %}
{% block row %}   {% for field in inline_admin_form.fields %}
    {% if field.name == 'name' %}
       
          {{ field.contents }}
       
    {% else %}
       {{ field.field }}
    {% endif %}
  {% endfor %} {% endblock %} {% endraw %}

Create get_absolute_url in your Child model to provide the detail view url:

# models.py
from django.db import models
from django.urls import reverse

class Parent(models.Model):
   name = models.CharField(max_length=200)

class Child(models.Model):
   parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='children')
   name = models.CharField(max_length=200)

   def get_absolute_url(self):
      return reverse('admin:yourapp_child_change', args=[str(self.id)])

Finally, create custom TabularInline and register the Child model in your admin.py:

# admin.py
from django.contrib import admin
from .models import Parent, Child

class ChildInline(admin.TabularInline):
   model = Child
   template = 'admin/edit_inline/tabular.html'

@admin.register(Parent)
class ParentAdmin(admin.ModelAdmin):
   inlines = [ChildInline]

@admin.register(Child)
class ChildAdmin(admin.ModelAdmin):
pass

5. Explanation:

- The custom admin/edit_inline/tabular.html extends Django’s original tabular template and overrides the `row` block.

- The `field.name == 'name'` condition will wrap the name of the child to a link. If there are other fields, it will render them normally

- The `inline_admin_form.original` provides access to the original object instance which is the `Child` object in this example.

- We use `get_absolute_url` method defined in the `Child` model to create link to detail view of Child object

By implementing this approach, each related object in the `TabularInline` will have a clickable link to its detail view in the Django admin.

More questions