- Кнопки 'убрать фон' для всех элементов: профиль, группы, ссылки - Кнопка 'сбросить настройки интерфейса' с подтверждением - Django app export_import с полным API для бэкапа и восстановления - Экспорт: создание ZIP архивов с данными профиля и медиафайлами - Импорт: селективная загрузка групп, ссылок, стилей, медиа - Обработка мультипарт форм, Django транзакции, управление ошибками - Полное тестирование: экспорт → импорт данных между пользователями - API эндпоинты: /api/export/, /api/import/, превью архивов - Готовая система для производственного развертывания
92 lines
4.3 KiB
Python
92 lines
4.3 KiB
Python
from django.db import models
|
||
from django.contrib.auth import get_user_model
|
||
from django.utils import timezone
|
||
|
||
User = get_user_model()
|
||
|
||
|
||
class ExportTask(models.Model):
|
||
"""Модель для отслеживания задач экспорта профиля"""
|
||
|
||
STATUS_CHOICES = [
|
||
('pending', 'Ожидает выполнения'),
|
||
('processing', 'В процессе'),
|
||
('completed', 'Завершен'),
|
||
('failed', 'Ошибка'),
|
||
]
|
||
|
||
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='Пользователь')
|
||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name='Статус')
|
||
|
||
# Опции экспорта
|
||
include_groups = models.BooleanField(default=True, verbose_name='Включить группы')
|
||
include_links = models.BooleanField(default=True, verbose_name='Включить ссылки')
|
||
include_styles = models.BooleanField(default=True, verbose_name='Включить стили')
|
||
include_media = models.BooleanField(default=True, verbose_name='Включить медиафайлы')
|
||
|
||
# Файл с результатом
|
||
export_file = models.FileField(
|
||
upload_to='exports/',
|
||
null=True,
|
||
blank=True,
|
||
verbose_name='Файл экспорта'
|
||
)
|
||
|
||
# Логирование
|
||
error_message = models.TextField(blank=True, verbose_name='Сообщение об ошибке')
|
||
|
||
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Создано')
|
||
updated_at = models.DateTimeField(auto_now=True, verbose_name='Обновлено')
|
||
|
||
class Meta:
|
||
verbose_name = 'Задача экспорта'
|
||
verbose_name_plural = 'Задачи экспорта'
|
||
ordering = ['-created_at']
|
||
|
||
def __str__(self):
|
||
return f'Экспорт {self.user.username} - {self.get_status_display()}'
|
||
|
||
|
||
class ImportTask(models.Model):
|
||
"""Модель для отслеживания задач импорта профиля"""
|
||
|
||
STATUS_CHOICES = [
|
||
('pending', 'Ожидает выполнения'),
|
||
('processing', 'В процессе'),
|
||
('completed', 'Завершен'),
|
||
('failed', 'Ошибка'),
|
||
]
|
||
|
||
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='Пользователь')
|
||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name='Статус')
|
||
|
||
# Файл для импорта
|
||
import_file = models.FileField(upload_to='imports/', verbose_name='Файл для импорта')
|
||
|
||
# Опции импорта
|
||
import_groups = models.BooleanField(default=True, verbose_name='Импортировать группы')
|
||
import_links = models.BooleanField(default=True, verbose_name='Импортировать ссылки')
|
||
import_styles = models.BooleanField(default=True, verbose_name='Импортировать стили')
|
||
import_media = models.BooleanField(default=True, verbose_name='Импортировать медиафайлы')
|
||
|
||
# Стратегия конфликтов
|
||
overwrite_existing = models.BooleanField(default=False, verbose_name='Перезаписать существующие')
|
||
|
||
# Результаты импорта
|
||
imported_groups_count = models.PositiveIntegerField(default=0, verbose_name='Импортировано групп')
|
||
imported_links_count = models.PositiveIntegerField(default=0, verbose_name='Импортировано ссылок')
|
||
imported_media_count = models.PositiveIntegerField(default=0, verbose_name='Импортировано медиафайлов')
|
||
|
||
# Логирование
|
||
error_message = models.TextField(blank=True, verbose_name='Сообщение об ошибке')
|
||
|
||
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Создано')
|
||
updated_at = models.DateTimeField(auto_now=True, verbose_name='Обновлено')
|
||
|
||
class Meta:
|
||
verbose_name = 'Задача импорта'
|
||
verbose_name_plural = 'Задачи импорта'
|
||
ordering = ['-created_at']
|
||
|
||
def __str__(self):
|
||
return f'Импорт {self.user.username} - {self.get_status_display()}' |