Как в Django сделать поиск в админке по полю ForeignKey?

В Django можно настроить поиск по полю ForeignKey в админке. Для этого необходимо определить метод get_search_results() в классе модели, который будет представлять эту связь ForeignKey.

Предположим, у нас есть модель Author с полем ForeignKey, указывающим на модель Book. Мы хотим, чтобы в админке можно было выполнять поиск авторов по имени книги.

Прежде всего, нужно определить метод get_search_results() в классе модели Author со следующей логикой:

class Author(models.Model):
    name = models.CharField(max_length=100)
    book = models.ForeignKey(Book, on_delete=models.CASCADE)

    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
        try:
            book = Book.objects.get(name__icontains=search_term)
            queryset |= self.model.objects.filter(book=book)
        except Book.DoesNotExist:
            pass
        return queryset, use_distinct

Внутри метода get_search_results() мы вызываем родительскую реализацию этого метода, чтобы получить изначальный queryset и флаг use_distinct. Затем мы пытаемся найти книгу, содержащую заданный поисковый термин (search_term), используя метод get() и метод вызываемого объекта Book. Если такая книга найдена, мы дополняем queryset, фильтруя все экземпляры модели Author, которые связаны с найденной книгой. Если книга не найдена, игнорируем исключение.

Затем в классе AuthorAdmin (или любом другом административном классе, в котором вы используете модель Author) нужно переопределить метод get_search_results() для передачи правильных данных в метод модели get_search_results():

class AuthorAdmin(admin.ModelAdmin):

    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
        if hasattr(self.model, 'get_search_results'):
            return self.model().get_search_results(request, queryset, search_term)
        return queryset, use_distinct

Определив эти методы в модели и админке, вы сможете выполнить поиск по имени книги в админке для модели Author.

Обратите внимание, что код представлен для Django 3.x версии. Некоторые детали могут отличаться для более ранних версий.