1

I have the following in my models.py:

class Size(models.Model):
    size = models.CharField(max_length=20, primary_key=True)

class Book(models.Model):
    title = models.CharField(max_length=100, primary_key=True)
    size = models.ForeignKey(Size, null=False)

class Pamphlet(models.Model):
    title = models.CharField(max_length=100, primary_key=True)
    size = models.ForeignKey(Size, null=False)
    book = models.ForeignKey(Book, null=True)

When the database is initially built the Size, Book, and Pamphlet tables are populated and each Book and Pamphlet is associated with a single size. However, the foreign key from Pamphlet to Book is not set.

It will be the responsibility of a user to go to the admin page and choose which book to associate with each pamphlet. Django's admin functionality makes it possible to set this column in the displayed table as editable, and it is smart enough to automatically generate a dropdown choice presenting all the possible books from the books table for the user to choose from.

However, this books table contains hundreds of choices, and I know that it will only make sense for the user to choose a book that is the same size as the pamphlet. So I would like to filter the options in the dropdown that Django generates and only show the books that share the same size with the Pamphlet.

How can I accomplish this?

I looked here: How do I filter ForeignKey choices in a Django ModelForm? but this doesn't seem to be referring to Django's Admin functionality.

Community
  • 1
  • 1
tadasajon
  • 14,276
  • 29
  • 92
  • 144

1 Answers1

1

Specialize the get_changelist_form method of the admin to return a custom form class. That form class can set the queryset attribute of its book field in its __init__ method depending on the instance argument it receives. EG:

class PamphletChangeListForm(forms.ModelForm):
    class Meta:
        model = Pamphlet

    def __init__(self, *args, **kwargs):
        super(PamphletChangeListForm, self).__init__(*args, **kwargs)
        instance = kwargs.get('instance')
        if instance:
            self.fields['book'].queryset = Book.objects.filter(size=instance__size)
Peter DeGlopper
  • 36,326
  • 7
  • 90
  • 83
  • 1
    If Django is 1.6+, omit `model= ...`, as per the "Note" in the linked docs. – frnhr Feb 23 '14 at 19:18
  • Thanks very much - this works. Any interest in taking a shot at this closely related question? http://stackoverflow.com/questions/21974827/django-how-can-i-make-a-cell-in-a-table-in-the-admin-inline-interface-editab – tadasajon Feb 23 '14 at 21:35