Копирование объектов в Django Admin

Дублирование мероприятий в Django Admin

В этом посте мы разберем код, который позволяет дублировать мероприятия в Django Admin. Код представляет собой действие администратора, которое можно применить к нескольким мероприятиям одновременно.

Код

def duplicate_model(modeladmin, request, queryset):
    """
    Дублирует мероприятия и связанные модели.
    """
    if queryset:
        obj_id = queryset.first().pk
        for model in queryset:
            model.pk = None
            model.save()
            _duplicate_related_models(model, obj_id)
            modeladmin.message_user(request, f"Дублирование прошло успешно, id - {model.pk}")
    else:
        modeladmin.message_user(request, "Нет мероприятий для дублирования")

def _duplicate_related_models(model, obj_id):
    """
    Копирует связанные модели для мероприятия.
    """
    related_models = [
        EventAdvantageInlineAdmin.model,
        EventHallImageInlineAdmin.model,
        EventWelcomeSpeechInlineAdmin.model,
        AdBlockEventInlineAdmin.model,
        SponsorEventInlineAdmin.model,
        SpecializationEventInlineAdmin.model,
        ProgramEventInlineAdmin.model,
        SponsorEventVideoInlineAdmin.model,
        EventPartnerInlineAdmin.model,
        EventOrganizerInlineAdmin.model,
        EventContactInlineAdmin.model,
    ]

    for inline in model._meta.get_fields():
        if isinstance(inline, ManyToOneRel) and issubclass(inline.related_model, tuple(related_models)):
            for related in inline.related_model.objects.filter(event_id=obj_id):
                related.pk = None
                related.event = model
                related.save()


duplicate_model.short_description = "Дублировать выбранное мероприятие"
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
    """Мероприятия"""
    
    actions = [duplicate_model]
    list_display = ["id", "name", "date_event"]
    list_display_links = ("name",)
    save_on_top = True
    inlines = [
        EventAdvantageInlineAdmin,
        EventHallImageInlineAdmin,
        EventWelcomeSpeechInlineAdmin,
        AdBlockEventInlineAdmin,
        SponsorEventInlineAdmin,
        SpecializationEventInlineAdmin,
        ProgramEventInlineAdmin,
        SponsorEventVideoInlineAdmin,
        EventPartnerInlineAdmin,
        EventOrganizerInlineAdmin,
        EventContactInlineAdmin,
    ]

Обзор

Код состоит из двух частей: действия администратора duplicate_model и регистрации этого действия для модели Event.

Действие администратора

Действие администратора duplicate_model принимает три аргумента: modeladminrequest и querysetmodeladmin - это экземпляр класса ModelAdminrequest - это запрос, который вызвал действие, а queryset - это набор объектов, к которым применено действие.

Действие делает следующее:

  1. Извлекает идентификатор первого объекта в наборе (obj_id).
  2. Проходит по каждому объекту в наборе и:
    • Устанавливает идентификатор объекта в None, чтобы создать новую копию.
    • Сохраняет объект.
    • Копирует связанные модели (см. ниже).
  3. Отображает сообщение об успешном дублировании.

Копирование связанных моделей

Код копирует связанные модели, которые имеют отношение к мероприятию. Это делается с помощью цикла по полям модели (model._meta.get_fields()). Если поле является отношением к другой модели (ManyToOneRel), код проверяет, является ли эта модель одной из перечисленных в условии (if issubclass(inline.related_model, ...)). Если да, то код копирует связанные объекты, устанавливая их идентификатор в None и сохраняя их.

Регистрация действия

Действие регистрируется для модели Event с помощью декоратора @admin.register(Event). Это позволяет применять действие к нескольким мероприятиям одновременно в интерфейсе администратора.

Результат

Выводы

Код позволяет дублировать мероприятия в Django Admin, копируя связанные модели. Это может быть полезно для создания копий мероприятий с сохранением связей между ними.