← Назад к вопросам
Как проходила работа с внутренними инструментами?
1.2 Junior🔥 101 комментариев
#Soft Skills
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Работа с внутренними инструментами
Внутренние инструменты (internal tools, admin panels, dashboards) — это неотъемлемая часть разработки. Это простой и быстрый способ автоматизировать рутинные задачи.
Типы внутренних инструментов
1. Admin Panels (административные панели)
Для управления данными приложения:
# Django Admin
from django.contrib.admin import AdminSite
from .models import User, Post
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'email', 'created_at')
search_fields = ('name', 'email')
list_filter = ('is_active', 'created_at')
def get_actions(self, request):
actions = super().get_actions(request)
# Добавил кастомное действие для рассылки
def send_newsletter(modeladmin, request, queryset):
for user in queryset:
send_email.delay(user.email) # Async task
send_newsletter.short_description = "Отправить рассылку"
actions['send_newsletter'] = (send_newsletter, 'send_newsletter',
send_newsletter.short_description)
return actions
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published', 'created_at')
list_filter = ('published',)
readonly_fields = ('created_at', 'updated_at')
2. Dashboards (аналитические панели)
Для мониторинга метрик и KPI:
# FastAPI + Streamlit для быстрого создания Dashboard
from fastapi import APIRouter
from sqlalchemy import func
from .models import User, Post
router = APIRouter(prefix="/admin/dashboard", tags=["dashboard"])
@router.get("/stats")
def get_stats(db):
return {
"total_users": db.query(User).count(),
"active_users": db.query(User).filter(User.is_active).count(),
"total_posts": db.query(Post).count(),
"posts_today": db.query(Post).filter(
Post.created_at >= datetime.now().date()
).count(),
"avg_posts_per_user": db.query(
func.avg(func.count(Post.id))
).group_by(Post.author_id).scalar()
}
@router.get("/charts/user-growth")
def user_growth_chart(db):
"""Данные для графика роста пользователей по дням"""
result = db.query(
func.date(User.created_at).label('date'),
func.count(User.id).label('count')
).group_by('date').order_by('date').all()
return [{"date": str(r[0]), "count": r[1]} for r in result]
3. CLI инструменты (командная строка)
Для автоматизации однократных задач:
import click
from django.core.management.base import BaseCommand
# Django Management Command
class Command(BaseCommand):
help = 'Очистить неактивных пользователей'
def add_arguments(self, parser):
parser.add_argument('--days', type=int, default=90,
help='Дни неактивности')
def handle(self, *args, **options):
days = options['days']
cutoff = datetime.now() - timedelta(days=days)
inactive = User.objects.filter(last_login__lt=cutoff)
count = inactive.delete()[0]
self.stdout.write(
self.style.SUCCESS(f'Удалено {count} неактивных пользователей')
)
# Click CLI
@click.group()
def cli():
pass
@cli.command()
@click.option('--batch-size', default=100, help='Размер батча')
@click.option('--dry-run', is_flag=True, help='Просто показать, что будет удалено')
def cleanup_inactive_users(batch_size, dry_run):
"""Очистить неактивных пользователей"""
cutoff = datetime.now() - timedelta(days=90)
inactive = User.objects.filter(last_login__lt=cutoff)
if dry_run:
click.echo(f"Будет удалено: {inactive.count()} пользователей")
return
deleted = 0
for i, user in enumerate(inactive):
user.delete()
deleted += 1
if (i + 1) % batch_size == 0:
click.echo(f"Обработано: {deleted}")
click.echo(click.style(f"✓ Удалено {deleted} пользователей", fg='green'))
if __name__ == '__main__':
cli()
4. Data Migration Scripts
Для миграции и трансформации данных:
from django.core.management.base import BaseCommand
from tqdm import tqdm
class Command(BaseCommand):
help = 'Мигрировать данные из старой системы'
def handle(self, *args, **options):
# Получить данные из старой БД
legacy_users = get_legacy_users() # API или SQL к старой БД
created = 0
skipped = 0
with transaction.atomic():
for legacy_user in tqdm(legacy_users, desc="Миграция пользователей"):
try:
user, created_flag = User.objects.get_or_create(
email=legacy_user['email'],
defaults={
'name': legacy_user['name'],
'legacy_id': legacy_user['id'],
}
)
if created_flag:
created += 1
else:
skipped += 1
except Exception as e:
self.stdout.write(
self.style.ERROR(f"Ошибка с {legacy_user['email']}: {e}")
)
self.stdout.write(
self.style.SUCCESS(
f"Создано: {created}, пропущено: {skipped}"
)
)
Мой опыт с внутренними инструментами
Проект 1: Система модерации контента
# Быстро создал админ-панель для модерирования постов
# Django Admin + кастомные actions
class PostModerationAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'status', 'created_at')
list_filter = ('status', 'created_at')
actions = ['approve', 'reject', 'send_feedback']
def approve(self, request, queryset):
count = queryset.update(status='approved')
notify_users.delay([p.author_id for p in queryset])
self.message_user(request, f"{count} постов одобрено")
def reject(self, request, queryset):
count = queryset.update(status='rejected')
self.message_user(request, f"{count} постов отклонено")
def send_feedback(self, request, queryset):
"""Отправить feedback авторам"""
for post in queryset:
send_notification.delay(
user_id=post.author_id,
message="Ваш пост нуждается в правках"
)
Этот инструмент спас ~5 часов в неделю для команды модерации.
Проект 2: Dashboard аналитики
# Создал FastAPI endpoint + Grafana dashboard
# Отслеживаю:
# - Активных пользователей
# - Ошибки в приложении
# - Время ответа API
# - Объём трафика
@router.get("/metrics/api-health")
def api_health(db):
last_hour = datetime.now() - timedelta(hours=1)
requests = db.query(
APILog.endpoint,
func.count().label('count'),
func.avg(APILog.response_time).label('avg_time'),
func.max(APILog.response_time).label('max_time')
).filter(APILog.created_at > last_hour).group_by(
APILog.endpoint
).all()
return [{"endpoint": r[0], "requests": r[1],
"avg_time": r[2], "max_time": r[3]} for r in requests]
Проект 3: Bulk операции
# CLI инструмент для бульк-операций
# Отправка email, обновление статусов, экспорт данных
@cli.command()
@click.argument('query')
@click.option('--action', required=True, help='Действие (email, update, export)')
@click.option('--batch-size', default=100)
def bulk_operation(query, action, batch_size):
"""Выполнить операцию для множества объектов"""
users = User.objects.filter(**parse_query(query))
total = users.count()
click.echo(f"Найдено {total} пользователей")
if not click.confirm('Продолжить?'):
click.echo('Отменено')
return
if action == 'email':
for batch in batch_iter(users, batch_size):
send_emails.delay([u.id for u in batch])
elif action == 'export':
with open('export.csv', 'w') as f:
writer = csv.DictWriter(f, fieldnames=['id', 'name', 'email'])
writer.writeheader()
for user in users:
writer.writerow(user.to_dict())
click.echo('Экспортировано в export.csv')
Лучшие практики
✅ Django Admin для быстрого CRUD
✅ CLI scripts для batch операций
✅ Dashboards для мониторинга
✅ Логирование всех действий (audit trail)
✅ Permissions и role-based access control
❌ Не деплой инструменты без review
❌ Не предоставляй доступ к production без необходимости
Внутренние инструменты экономят тонны времени и улучшают качество операций.