Как настроить поиск по спискам изменений в 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)
Я хочу иметь возможность искать в списках изменений этих соответствующих моделей, используя любое из следующих полей:
- поле OfficialAirportName модели AirportAdministrativeData, или,
- поле 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", он вам не нужен.