Admin built in add/change forms

Hi - I am wondering what is the best method and how to add in an informational field to the built-in admin add/change forms.

Here is my case:

I have 3 models each one is tied to another by a foreign key
investor → investment
distribution → investment

So with proper a query I can easily look up from the distribution table which investor received which distribution

If I want to add a distribution using the built in Django admin forms - the selection option for “investment” field for the distribution add form the dropdown list will include all the investments. The issue I am having is, if I have the same investment name for 2 investors, I do not know which option to select. So I would want the form to lookup the Investor using Investment → Investor while on the distribution add/change this way when I add a distribution to an Investment I can select which investor it applies to.

i.e.
Investor Paul has Investments AAPL, GME, BB
Investor Alan has Investments TSLA, GME
Adding distribution for Investment GME —> that form would should 2 GME options but I would like to know which is Pauls and which is Alans

On the admin homepage for distributions I can see this using the list_display and throwing in a function to call a lookup (code pasted below) but I would need the same information on the add/change form

models.py

class Distribution(models.Model):
    distribution_id = models.AutoField(primary_key=True)
    investment = models.ForeignKey('Investment', models.DO_NOTHING, blank=True, null=True)
    distribution_amount = models.DecimalField(max_digits=18, decimal_places=4, blank=True, null=True)
    distribution_date = models.DateField(blank=True, null=True)

    class Meta:
        db_table = 'distribution'

    def __str__(self):
        return f'{self.investment} for {self.distribution_amount}'


class Investment(models.Model):
    investment_id = models.AutoField(primary_key=True)
    investment_name = models.CharField(max_length=255, blank=True, null=True)
    initial_investment = models.DecimalField(max_digits=19, decimal_places=4, blank=True, null=True)
    date_of_investment = models.DateField(blank=True, null=True)
    investor = models.ForeignKey('Investor', models.DO_NOTHING, blank=True, null=True)

    class Meta:
        ordering = ('investment_name',)

    def __str__(self):
        return self.investment_name


class Investor(models.Model):
    investor_id = models.AutoField(primary_key=True)
    first_name = models.CharField(max_length=255, blank=True, null=True)
    last_name = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        ordering = ('last_name',)

    def __str__(self):
        return f'{self.last_name}, {self.first_name}'

admin.py

from django.contrib import admin

# Register your models here.
from .models import Distribution, Investment, Investor


@admin.register(Distribution)
class DistributionAdmin(admin.ModelAdmin):
    list_display = ('investment', 'get_investor' ,'distribution_amount')


    @admin.display(description='Investor Name')
    def get_investor(self, obj):
        return obj.investment.investor


@admin.register(Investment)
class InvestmentAdmin(admin.ModelAdmin):
    list_display = ('investment_name', 'investor')


@admin.register(Investor)
class InvestorAdmin(admin.ModelAdmin):
    list_display = ('full_name_display',)

    @admin.display(description='Investor Name')
    def full_name_display(self, obj):
        return f'{obj.last_name}, {obj.first_name}'

Hi BoredCPA,

If you’re looking to customize the label of the options in the form representation of a model, you’ll need to create a new ModelChoiceField subclass, override label_from_instance(ignore the iterator part, the relevant info is just below it), then create a form for your ModelAdmin class, and specify the new form. Alternatively, you can change the definition of the __str__ method on Investment to include the investor’s name. However, the problem with that is you can easily create N+1 queries.

Let me know if that doesn’t make sense.