forms.ModelChoiceField の queryset で HttpRequest を使いたい

115 views
Skip to first unread message

tosik

unread,
Nov 10, 2009, 8:04:43 AM11/10/09
to django-ja
はじめまして、廣岡と申します。
先週あたりから Django を使い始めた初心者です。

現在、admin を使ったデータ入稿システムを作成しています。
入力(変更)画面でプルダウンのフォームを使おうと以下のようにしました。

class ItemAdminForm(forms.ModelForm):
shop = forms.ModelChoiceField(queryset=Shop.objects)
class Meta:
model = Shop

class ItemAdmin(admin.ModelAdmin):
form = ItemAdminForm

admin.site.register(Item, ItemAdmin)

これは Item の入力時に Shop を一覧から指定できるようにしています。
# Shop は既存DBの事情により IntegerField となっています。

ここまでは問題なくできました。
次に、このプルダウンの中身をログインユーザの情報によって変更させたいと思い、
queryset へ与える Shop.objects.filter() を使いました。
ところが、ログインユーザを取得するには HttpRequest のインスタンスが必要で、
この段階ではどうしても取得ができませんでした。

どのようにすればログインユーザを使って queryset を作成することができますか。
以上です。よろしくお願いいたします。

Ian Lewis

unread,
Nov 11, 2009, 6:37:32 AM11/11/09
to djan...@googlegroups.com
こんにちは、イアンです。

Item モデルの中に shopという ForeignKeyがあると思います。

そうした場合に、 admin クラスに formfield_for_foreignkey[1] というメソッドを実装すると以下の問題を解決できると思います。

こういうふうに書けば request を使えると思います。

class ItemAdmin(admin.ModelAdmin):
...
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'user' and not request.user.is_superuser:
kwargs["queryset"] = Shop.objects.filter(user=request.user)
return db_field.formfield(**kwargs)
return super(ItemAdmin,
self).formfield_for_foreignkey(db_field, request, **kwargs)

[1]
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_foreignkey

2009/11/10 tosik <toshi....@gmail.com>:
--
=======================================
株式会社ビープラウド イアン・ルイス
〒150-0012
東京都渋谷区広尾1-11-2アイオス広尾ビル604
email: ianm...@beproud.jp
TEL:03-5795-2707
FAX:03-5795-2708
http://www.beproud.jp/
=======================================

Ian Lewis

unread,
Nov 11, 2009, 6:43:38 AM11/11/09
to djan...@googlegroups.com
あ、

漏れましたが、下のformfield_for_foreignkeyは Django 1.1 のみです。 Django 1.0
はえらいことしないとrequest使えません。

イアン

2009/11/11 Ian Lewis <ianm...@gmail.com>:

Toshiyuki Hirooka

unread,
Nov 11, 2009, 8:24:56 AM11/11/09
to djan...@googlegroups.com
廣岡です。
イアンさん、ありがとうございます。
幸いにも Django1.1 を使用しています。

現在、帰宅しまして作業環境が手元にありませんので試してはいないのですが、
実は、Item もでるの shop は、既存システムの都合上 ForeignKey ではなく IntegerField となっています。
ですので、IntegerField を PrimaryKey とした Shop.id を探すような仕組みになっています。
この場合でも formfield_for_foreignkey を使って制御は可能なのでしょうか?

2009/11/11 Ian Lewis <ianm...@gmail.com>:

Ian Lewis

unread,
Nov 11, 2009, 10:00:12 AM11/11/09
to djan...@googlegroups.com
廣岡さん、

イアンです。

ForeignKeyでない限り、formfield_for_foreignkeyは使えないと思います。

そうした場合は、結構厳しいと思いますが、ModelAdmin の change_view
を自分で実装するのがおすすめです。そのなかに、自分のフォームインスタンスを作成する感じになると思います。Formは__init__でリクエストを引数として取得して、self.fieldsにrequestを使って、自分のModelChoiceFieldを入れる感じになると思います。

以下のコードを全然保証してないんですが、

class ItemAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
request = kwargs.pop("request") if "request" in kwargs else None
if request:
qs = Shop.objects.filter(user=request.user)
else:
#Error?
qs = Show.objects.all()
self.fields["shop"] = forms.ModelChoiceField(queryset=qs)
return super(ItemAdminForm,self).__init__(*args, **kwargs)

class ItemAdmin(models.ModelAdmin):
...
def change_view(self, request, object_id, extra_context=None):
# これは多分、django/contrib/admin/options.py からほぼコピーする
...
adminForm = ItemAdminForm(request=request)
...


2009/11/11 Toshiyuki Hirooka <toshi....@gmail.com>:

Toshiyuki Hirooka

unread,
Nov 12, 2009, 1:11:05 AM11/12/09
to djan...@googlegroups.com
イアンさん、
廣岡です。

コードの例、ありがとうございます。
いただいたコードから何をしたいか、ということは理解できましたが、
現在、方針に若干の変更がありまして、この方法は繰越となったので、
簡単にやってみる程度でいただいたコードを試してみました。

まず、問題が出たのは、
self.fields["shop"] = forms.ModelChoiceField(queryset=qs)
の個所です。fields ないといわれてしまったので、後回しに。

つぎに、change_view ですが、
adminForm に代入する個所を
adminForm = ItemAdminForm(request=request)
に置き換えると、

Exception Value: Caught an exception while rendering: 'BoundField'
object is not iterable

Original Traceback (most recent call last):
File "/usr/lib/python2.5/site-packages/django/template/debug.py",
line 71, in render_node
result = node.render(context)
File "/usr/lib/python2.5/site-packages/django/template/defaulttags.py",
line 125, in render
values = list(values)
TypeError: 'BoundField' object is not iterable

Exception Location:
/usr/lib/python2.5/site-packages/django/template/debug.py in
render_node, line 81

となってしまいましたので、どういうことだろうと少し考えています。
また、同じく add_view も同様にオーバーライドしましたが同じでした。


以上が報告です。

もし解決案などありましたら返信をいただければと思いますが、
これについて、私側での現在は解決を先延ばしにする予定です。

以上です。

2009/11/12 Ian Lewis <ianm...@gmail.com>:

Reply all
Reply to author
Forward
0 new messages