Сделайте настраиваемое поле HTML сортируемым в django-admin

#django #django-admin

Вопрос:

У меня есть очень простая модель, которая состоит только из названия и серийного номера. Я могу использовать этот серийный номер, чтобы запросить статус в API, и я хочу отобразить результат в виде значка/HTML:

 class ProductAdminForm(admin.ModelAdmin):
    class Meta:
        model = Product
        fields = ["get_status", "name",]

    def get_status(self, obj):
        status = get_status_from_API(obj)["status"]
        style = """style="height: 10px; width: 10px; border-radius: 50%; COLOR display: inline-block;" """
    
        if status == 2:
            new_style = style.replace("COLOR", "background-color: green;")
        elif status == 1:
            new_style = style.replace("COLOR", "background-color: red;")
        else:
            new_style = style.replace("COLOR", "background-color: grey;")
        return mark_safe(f"""<span class="dot" {new_style}></span>""")
 

Как я могу сделать get_status столбец сортируемым?

Ответ №1:

Вы можете сортировать только по свойствам в базе данных.

Обычно элементы list_display, которые не являются фактическими полями базы данных, не могут использоваться при сортировке (поскольку Django выполняет всю сортировку на уровне базы данных).

https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display

Это означает, что вы не можете сортировать по статусу объекта в API. Однако вы можете выполнить сортировку по какому-либо другому свойству, например по серийному номеру, установив admin_order_field .

Если вы действительно хотите отсортировать статус, вам нужно каким-то образом сохранить этот статус в базе данных.

Одним из решений было бы периодически вызывать команду управления, которая извлекает состояние всех объектов и сохраняет результат в базе данных.

Это позволяет сортировать (и фильтровать) объекты по их статусу.

Хранение результатов API в базе данных также имеет преимущество в том, что при просмотре объектов в администраторе не требуется выполнять какие-либо вызовы API. Это особенно полезно, когда API не работает/работает медленно. Очевидным недостатком является то, что результаты могут быть немного устаревшими, в зависимости от частоты вызова команды обновления.