Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как изменить отображение модели в админке
В Django администраторская панель контролируется классом ModelAdmin, который определяет, как модели отображаются и редактируются в интерфейсе.
1. Базовое изменение отображения
# models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
# admin.py
from django.contrib import admin
from .models import Product
# Вариант 1: Простая регистрация (минимальное отображение)
admin.site.register(Product)
# Вариант 2: Кастомизация через ModelAdmin
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
# Какие поля показывать в списке
list_display = ('name', 'price', 'stock', 'created_at')
# Какие поля доступны для фильтрации
list_filter = ('created_at', 'price', 'stock')
# Поиск по этим полям
search_fields = ('name', 'description')
# Какие поля редактируются в списке
list_editable = ('price', 'stock')
# Количество элементов на странице
list_per_page = 50
2. Кастомизация деталей записи
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
# Порядок полей при редактировании
fields = ('name', 'price', 'stock', 'description')
# Группировка полей в категории (fieldsets)
fieldsets = (
('Основная информация', {
'fields': ('name', 'description')
}),
('Цена и наличие', {
'fields': ('price', 'stock')
}),
('Служебная информация', {
'fields': ('created_at',),
'classes': ('collapse',) # Свёрнутый блок
})
)
# Поля, доступные только для чтения
readonly_fields = ('created_at',)
3. Форматирование столбцов
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'formatted_price', 'stock_status', 'created_at')
# Кастомный метод для отображения цены
@admin.display(description='Цена ($)', ordering='price')
def formatted_price(self, obj):
return f"${obj.price:.2f}"
# Кастомный метод для статуса наличия
@admin.display(description='Статус', ordering='stock')
def stock_status(self, obj):
if obj.stock > 10:
status = "✓ В наличии"
color = "green"
elif obj.stock > 0:
status = "⚠ Заканчивается"
color = "orange"
else:
status = "✗ Нет в наличии"
color = "red"
return f'<span style="color: {color};">{status}</span>'
# Разрешить HTML в таблице
formatted_price.allow_tags = True
4. Встроенное редактирование связанных моделей
from django.contrib import admin
from .models import Product, Review
# Встроенное редактирование отзывов внутри Product
class ReviewInline(admin.TabularInline):
model = Review
extra = 1 # Дополнительная пустая форма
fields = ('author', 'rating', 'comment')
readonly_fields = ('created_at',)
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'price')
inlines = [ReviewInline] # Встроить Review в Product
5. Кастомные действия (actions)
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'price', 'stock')
actions = ['mark_out_of_stock', 'apply_discount']
@admin.action(description="Отметить как нет в наличии")
def mark_out_of_stock(self, request, queryset):
updated = queryset.update(stock=0)
self.message_user(request, f"{updated} товаров отмечено как нет в наличии")
@admin.action(description="Применить 20% скидку")
def apply_discount(self, request, queryset):
for product in queryset:
product.price *= 0.8
product.save()
self.message_user(request, f"Скидка применена {queryset.count()} товарам")
6. Сортировка и фильтры
from django.contrib import admin
from django.utils.html import format_html
from datetime import datetime, timedelta
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'price', 'stock')
list_filter = (
'created_at',
('price', admin.NumericRangeFilter), # Фильтр по диапазону
('stock', admin.BooleanFieldListFilter), # Есть / нет
)
# Сортировка по умолчанию
ordering = ('-created_at',) # Новые первыми
# Дополнительная фильтрация
def get_list_filter(self, request):
list_filter = list(self.list_filter)
if request.user.is_superuser:
list_filter.append('is_archived')
return list_filter
7. Поиск с улучшениями
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
# Поиск по нескольким полям
search_fields = ('name', 'description', 'sku')
# Кастомный поиск
def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super().get_search_results(
request, queryset, search_term
)
# Дополнительная фильтрация
try:
price = float(search_term)
queryset |= self.model.objects.filter(price=price)
except ValueError:
pass
return queryset, use_distinct
8. Кастомные форма и валидация
from django import forms
from django.contrib import admin
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = '__all__'
def clean(self):
cleaned_data = super().clean()
# Валидация цены
if cleaned_data.get('price') and cleaned_data['price'] < 0:
raise forms.ValidationError("Цена не может быть отрицательной")
# Валидация наличия
if cleaned_data.get('stock') and cleaned_data['stock'] < 0:
raise forms.ValidationError("Наличие не может быть отрицательным")
return cleaned_data
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
form = ProductForm
9. Изменение цвета и стилей
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'colored_price', 'stock')
@admin.display(description='Цена')
def colored_price(self, obj):
if obj.price > 100:
color = 'red'
elif obj.price > 50:
color = 'orange'
else:
color = 'green'
return format_html(
'<span style="color: {}; font-weight: bold;">${:.2f}</span>',
color, obj.price
)
10. Разрешения и видимость
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
def get_readonly_fields(self, request):
# Некоторые поля только для суперпользователя
if request.user.is_superuser:
return self.readonly_fields
return list(self.readonly_fields) + ['created_at', 'price']
def get_list_display(self, request):
# Разные столбцы для разных пользователей
if request.user.is_staff and not request.user.is_superuser:
return ('name', 'stock')
return self.list_display
def get_queryset(self, request):
# Фильтрация данных по пермиссиям
qs = super().get_queryset(request)
if not request.user.is_superuser:
qs = qs.filter(is_archived=False)
return qs
11. Полный пример
from django.contrib import admin
from django.utils.html import format_html
from .models import Product
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
# Список
list_display = ('name', 'formatted_price', 'stock_status', 'created_date')
list_filter = ('created_at', 'price')
search_fields = ('name', 'description')
list_per_page = 25
ordering = ('-created_at',)
# Редактирование
fieldsets = (
('Основное', {
'fields': ('name', 'description')
}),
('Цена и наличие', {
'fields': ('price', 'stock')
}),
('Служебное', {
'fields': ('created_at',),
'classes': ('collapse',)
})
)
readonly_fields = ('created_at',)
# Действия
actions = ['mark_out_of_stock']
@admin.display(description='Цена')
def formatted_price(self, obj):
return f"${obj.price:.2f}"
@admin.display(description='Статус')
def stock_status(self, obj):
status = "Да" if obj.stock > 0 else "Нет"
color = "green" if obj.stock > 0 else "red"
return format_html(
'<span style="color: {};">{}</span>',
color, status
)
@admin.display(description='Дата', ordering='created_at')
def created_date(self, obj):
return obj.created_at.strftime('%d.%m.%Y')
@admin.action(description="Отметить нет в наличии")
def mark_out_of_stock(self, request, queryset):
updated = queryset.update(stock=0)
self.message_user(request, f"Обновлено {updated} товаров")
Заключение
Кастомизация админки включает:
- list_display — столбцы в списке
- list_filter — фильтры
- search_fields — поиск
- fieldsets — группировка полей
- readonly_fields — поля только для чтения
- actions — кастомные действия
- inlines — встроенное редактирование связанных моделей
- форматирование — кастомные методы и HTML
Правильно настроенная админка значительно упрощает работу с данными!