Admin actionsを使う6 - データをコピーする編

手間を省くために

Admin siteで重複するデータを入力する場合、いちいち入力画面から登録するのは面倒だと思いませんか?
そこで、Admin actionsを使って省入力化してみましょう。

ベースmodel, admin作成

確認するために伝票みたいなmodelを作成します。

models.py

from django.db import models
from django.contrib.auth.models import User
import datetime

class Voucher(models.Model):
    title = models.CharField(max_length = 50)
    amount = models.IntegerField(default=0)
    author = models.ForeignKey(User)

    def __unicode__(self):
        return self.title

admin.py

from django.contrib import admin
from appname.models import Voucher

class VoucherAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', 'amount', 'author')

admin.site.register(Voucher, VoucherAdmin)

サンプルデータを追加

Admin siteからサンプルデータを以下のように追加します。

adminaction06_01

Change listは以下の通りです。

adminaction06_02

Admin actions作成

選択したオブジェクトをコピーしたadmin actionsを作成します。

admin.py

from django.contrib import admin
from appname.models import Voucher

def clone_objects(objects):
    def clone(from_object):
        args = dict([(fld.name, getattr(from_object, fld.name))
            for fld in from_object._meta.fields
                in fld is not from_object._meta.pk]);
        return from_object.__class__.objects.create(**args))

    if not hasattr(objects, '__iter__'):
        objects = [objects]

    for object in objects:
        obj = clone(object)
        obj.save()

class VoucherAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', 'amount', 'author')
    actions = ['action_clone']

    def action_clone(self, request, queryset):
        clone_objects(queryset)

admin.site.register(Voucher, VoucherAdmin)

Admin actionsの確認

以下は実行後の画面です。

adminaction06_03

次に複数選択した場合も実行してみました。

選択時の画面

adminaction06_04

実行後の画面です。

adminaction06_05

どの伝票のコピー?

複数の伝票をコピーする場合、コピー元を表記したい場合があります。
上記のadmin.pyを修正して"title"を"title (No.idの複製伝票)"とします。
そして、'author'は'action_clone'の実行者名にします。

admin.py

#-*- encoding:utf-8 -*-

from django.contrib import admin
from appname.models import Voucher

def clone_objects(objects):
    def clone(from_object):
        args = dict([(fld.name, getattr(from_object, fld.name))
            for fld in from_object._meta.fields
                in fld is not from_object._meta.pk]);

        id = str(getattr(from_object, 'id')
        title = getattr(from_object, 'title')
        user = getattr(from_object, 'author')

        args['title'] = title + u' (No.' + id + u'の複製伝票)'
        args['author'] = user

        return from_object.__class__.objects.create(**args))

    if not hasattr(objects, '__iter__'):
        objects = [objects]

    for object in objects:
        obj = clone(object)
        obj.save()

class VoucherAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', 'amount', 'author')
    actions = ['action_clone']

    def action_clone(self, request, queryset):
        clone_objects(queryset)

admin.site.register(Voucher, VoucherAdmin)

上記のコードに修正し、複数選択した状態で実行してみます。

複数選択時の画面

adminaction06_06

実行後の画面

adminaction06_07

たくさんのデータを作成する場合など利用してみてはどうでしょうか?

twitter 2009-10-09 21:18:13.038865

関連ページ

参照サイト

Recent Updates

URLConf Tip 01 - キャプチャの有無にかかわらず同一のviewで処理する
Markdownの入力補助"wmd"をAdmin siteで使う
ModelFormでfieldのwidgetを変更する
動的なformを作る 6 - Dynamic Inline Admin site編
Formsetsを使う3 - inlineformset_factory編
動的なformを作る 5 - django-dynamic-formset編
Formクラスからメディアを定義する
複数のmodelを結合する 2 - Proxy model編
複数のmodelを結合する 1
ModelFormでfieldの表示順番を変える
Admin siteのwidgetを個別に変更する
formfield_overridesを使ってAdmin siteのwidgetを変更する
Admin siteのlist_displayをカスタマイズする - リンク編
Admin siteのlist_displayをカスタマイズする - 基本編
Admin siteのTextareaの高さを自在に変更する - admin.py編