Как настроить поиск по спискам изменений в django-admin в моделях, связанных через ForeignKeys?

Я создал следующие четыре класса моделей:

class InfrastructureModel(models.Model):
    ENTRY_ACTIVE_YES_NO_CHOICES = (
        (True, 'Yes'),
        (False, 'No'))

    entryActiveYesNo = models.BooleanField(r"Is this database entry still active? (YES/NO)",
                                      null=False,
                                      blank=False,
                                      unique=False,
                                      choices=ENTRY_ACTIVE_YES_NO_CHOICES,
                                      help_text=r"Is this database entry still active? If it's been changed/modified to something else, mark this as False.")

class AirportAdministrativeData(InfrastructureModel):
    officialAirportName=models.CharField(r"Airport's Official Name",
                                         max_length=100,
                                         null=False, 
                                         blank=False, 
                                         unique=True,
                                         help_text=r"Offical name of the Airport")
    def __str__(self):
        return self.officialAirportName

class AirportAlternateName(InfrastructureModel):
    parentAirport=models.ForeignKey(AirportAdministrativeData,on_delete=models.RESTRICT,limit_choices_to={'entryActiveYesNo': True},verbose_name="Parent Airport",related_name='AirportOfficialName')
    alternateAirportName=models.CharField(r"Airport's Alternate Name",
                                          max_length=100, 
                                          null=False, 
                                          blank=False,
                                          unique=True,
                                          help_text=r"Alternate name of the Airport, if any.")

class AirportLocation(InfrastructureModel):
    parentAirport=models.ForeignKey(AirportAdministrativeData,on_delete=models.RESTRICT,limit_choices_to={'entryActiveYesNo': True},verbose_name="Parent Airport")
    latitude=models.DecimalField(max_digits=9, decimal_places=6)
    longitude=models.DecimalField(max_digits=9, decimal_places=6)
    airportAddress=models.CharField(r"Airport's Address",
                                          max_length=200, 
                                          null=False, 
                                          blank=False,
                                          unique=True,
                                          help_text=r"Airport's Address")
    airportState=models.ForeignKey(State,on_delete=models.RESTRICT,limit_choices_to={'entryActiveYesNo': True},verbose_name="State")

А их соответствующие классы администраторов следующие:

class AirportAdministrativeDataAdmin(admin.ModelAdmin):
    fields = ['officialAirportName', 'entryActiveYesNo']
    list_display = ('officialAirportName', 'entryActiveYesNo')
    search_fields = ['officialAirportName']
    search_help_text="Seach here for offical/alternate name of any airport in the Database."
class AirportAlternateNameAdmin(admin.ModelAdmin):
    fields = ['parentAirport', 'alternateAirportName', 'entryActiveYesNo']
    list_display = ('parentAirport', 'alternateAirportName', 'entryActiveYesNo')
    search_fields = ['alternateAirportName']
    search_help_text="Seach here for offical/alternate name of any airport in the Database."
class AirportLocationAdmin(admin.ModelAdmin):
    fields = ['parentAirport', 'latitude', 'longitude', 'airportAddress', 'airportState', 'entryActiveYesNo']
    list_display = ('parentAirport', 'latitude', 'longitude', 'airportAddress', 'airportState', 'entryActiveYesNo')
    #search_fields = ['parentAirport']
    search_help_text="Seach here for offical/alternate name of any airport in the Database."

А их соответствующие регистрации на сайте администратора выглядят следующим образом:

admin.site.register(AirportAdministrativeData,AirportAdministrativeDataAdmin)
admin.site.register(AirportAlternateName, AirportAlternateNameAdmin)
admin.site.register(AirportLocation, AirportLocationAdmin)

Я хочу иметь возможность искать в списках изменений этих соответствующих моделей, используя любое из следующих полей:

  1. поле OfficialAirportName модели AirportAdministrativeData, или,
  2. поле alternateAirportName модели аэропорта.

и вернуть соответствующий элемент поиска.

Я прочитал несколько статей, таких как документация django о ForeignKey.related_name и этот stackoverflow q&a. Но мой новичок все еще не может реализовать эту функцию. Пожалуйста, помогите!

Для добавления поля поиска из связанной модели необходимо использовать ту же нотацию, что и в filter(), т.е. путь с именами полей, разделенных двойными знаками подчеркивания.

Первое поле поиска

Чтобы добавить AirportAdministrativeData.officialAirportName в качестве поля поиска в список изменений AirportLocation, вы добавляете следующее: 'parentAirport__officialAirportName.

Второе поле поиска

Для 2-го поля поиска альтернативного имени необходимо перейти на один уровень глубже и использовать "связанное имя", которое является обратным отношением от AirportAdministrativeDataAdmin к AirportAlternateNameAdmin:

'parentAirport__AirportOfficialName__alternateAirportName'

Result

По умолчанию поля поиска комбинируются с OR, поэтому вы можете добавить 2-е поле поиска, и оно будет фильтровать объекты, которые соответствуют тому или другому:

class AirportLocationAdmin(admin.ModelAdmin):
    ...
    search_fields = [
        'parentAirport__officialAirportName',
        'parentAirport__AirportOfficialName__alternateAirportName'
    ]
    ...

Два дополнительных предложения, если позволите:

  • В Python свойства метода должны быть в змеином регистре, как вы видите в классах Admin. Поэтому я бы предложил переименовать все имена полей в ваших моделях, а также определения "related_name". Смотрите PEP8 для получения дополнительной информации об официальном стиле кодирования для Python
  • .
  • "r" перед вашими строками устарел. Это означает, что вы определяете строки регулярных выражений, что здесь не имеет смысла. Советую убрать "r", он вам не нужен.
Вернуться на верх