Admin actionsを使う4 - ForeignKeyデータを一括更新編

Admin actionsの利用方法

Admin actionsはフラグをたてたり、更新、削除など色々用途はありますが、だいたいBoolenField, CharField やIntegerFieldなどに対しての処理です。
ForeignKeyを対象に出来たら便利だと思いませんか?

仕様

一括更新の手順は以下の通りです。

  1. 変更するデータを選択します。
  2. 一括更新のアクションを選択して、実行ボタンをクリック。
  3. 遷移した画面から変更するデータを選択し、更新ボタンをクリックして処理実行。

model作成

ForeignKeyを含んだmodelを作成します。

models.py

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length = 100)

    def __unicode__(self):
        return self.name

class Product(models.Model):
    category = models.ForeignKey(Category, verbose_name = 'categories')
    name = models.CharField(max_length = 100)
    price = models.DecimalField(max_digits = 15, decimal_places = 2)

    def __unicode__(self):
        return self.name

admin作成

ベースのAdminを作成します。

admin.py

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

class ProductAdmin(admin.ModelAdmin):
    list_display = ('name', 'price', 'category', )

admin.site.register(Product, ProductAdmin)

modelにデータ追加

サンプルデータを追加します。

>>> from appname.models import Product, Category
>>>Category.objects.create(name = 'PC')
>>>Category.objects.create(name = 'Mac')
>>>c1 = Category.objects.get(pk = 1)
>>>c2 = Category.objects.get(pk = 2)
>>>Product.objects.create(category = c1, name = 'HP Mini', price = 100)
>>>Product.objects.create(category = c1, name = 'iPhone', price = 150)
>>>Product.objects.create(category = c2, name = 'MacBook', price = 200)
>>>Product.objects.create(category = c2, name = 'MacBook Air', price = 250)
>>>Product.objects.create(category = c2, name = 'Mac Pro', price = 300)

Change listは以下の通りです。

adminactions01

Admin actionsの作成

まずModelChoiceFieldを利用するためforms.pyを作成します。

forms.py

from appname.models import Category
from django import forms

class CategoryForm(forms.Form):
    category = foms.ModelChoiceField(queryset = Category.objects.all())

次にアクションを定義します。

admin.py

from django.contrib import admin
from appname.models import Product
from appname.forms import ProductForm
from django.shortcuts import render_to_response
from django.template import RequestContext

class ProductAdmin(admin.ModelAdmin):
    list_display = ('name', 'price', 'category', )

    actions = ['set_category_action']

    def set_category_action(self, request, queryset):
        if 'do_action' in request.POST:
            form = CategoryForm(request.POST)
            if forms.is_valid():
                queryset.update(category = form.cleaned_data['category'])
                return
        else:
            form = CategoryForm()
        return render_to_response(
            'admin/set_category.html',
            {'title': u'Change Category', 'objects': queryset, 'form': form},
            context_instance = RequestContext(request))
    set_category_action.short_description = u'Set Category'

最後にAdmin site内に表示するtemplateを作成します。

admin/set_category.html

{% extends "admin/base_site.html" %}

{% block content %}
<form action = "" method = "POST">
    <input type = "hidden" name = "action" value = "set_category_action">
    <input type = "hidden" name = "do_action" value = "yes">
    <div>
        {{ form.category }}
        <input type = "submit" class = "default" style = "float: none" value = "更新">
        {{ form.category.errors }}
    </div>
    <ul>
        {% for object in objects %}
        <li>
            <a href = "{{ obkect.pk }}/">{{ object.name }}</a> - {{ object.category }}
            <input type = "hidden" name = "_selected_action" value = "{{ object.pk }}">
        </li>
        {% endfor %}
    </ul>
</form>
{% endblock %}

動作確認

動作させてみます。

  1. 変更するデータを選択、Set Categoryアクションを選択し実行ボタンをクリックします。
    adminactions02

  2. コンボボックスからCategoryを選択し、更新ボタンをクリックすると処理が実行されます。
    adminactions03

  3. 選択したデータが変更されたことを確認してください。
    adminactions04

twitter 2009-08-31 21:58:37.224298

関連ページ

参照サイト

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編