In the Django admin interface, is there a way to duplicate an item?

Question:

Just wondering if there is an easy way to add the functionality to duplicate an existing listing in the admin interface?

In data entry we have run into a situation where a lot of items share generic data with another item, and to save time it would be very nice to quickly duplicate an existing listing and only alter the changed data. Using a better model structure would be one way of reducing the duplication of the data, but there may be situation where the duplicated data needs to be changed on an individual basis in the future.

Asked By: sesh

||

Answers:

You can save as by just enabling adding this to your ModelAdmin:

save_as = True

This replaces the “Save and add another” button with a “Save as” button. “Save as” means the object will be saved as a new object (with a new ID), rather than the old object.

Answered By: Harley Holcombe

There’s a better (but not built-in) solution here:

https://github.com/RealGeeks/django-modelclone

From their README:

Django Admin has a save_as feature that adds a new button to your
Change page to save a new instance of that object.

I don’t like the way this feature works because you will save an
identical copy of the original object (if you don’t get validation
errors) as soon as you click that link, and if you forget to make the
small changes that you wanted in the new object you will end up with a
duplicate of the existing object.

On the other hand, django-modelclone offers an intermediate view, that
basically pre-fills the form for you. So you can modify and then save
a new instance. Or just go away without side effects.

Answered By: kontextify

You can also apply this method: https://stackoverflow.com/a/4054256/7995920

In my case, with unique constraint in the ‘name’ field, this action works, and can be requested from any form:


def duplicate_jorn(modeladmin, request, queryset):
    post_url = request.META['HTTP_REFERER']

    for object in queryset:
        object.id = None
        object.name = object.name+'-b'
        object.save()

    return HttpResponseRedirect(post_url)

Answered By: Abel