editor フィールドにログインユーザのidを自動的に入れる方法について

1,230 views
Skip to first unread message

jun

unread,
Oct 30, 2006, 11:21:03 AM10/30/06
to django-ja
はじめまして、林と申します。
はじめて投稿させていただきます。

Django のModel
の設計に関して質問があるのですが、管理画面において"editor"のid
が自動的に入るような設定はできないでしょうか?

class Hoge(models.Model):
title = models.CharField(maxlength=200)
editor = models.ForeignKey(User)
edit_date = models.DateTimeField(auto_now=True)

class Admin:
pass

のようなモデルがあった場合に、管理画面でユーザを選択しなくても、ログインしているユーザのidが自動的に入るようにしたいのです。

Model のdefault で対応できないか、session
の値を取れないか、save()
をオーバーライドして対応できないか、など調べてみたのですが分からない状況です。
モデル定義が、ログインの有無と独立であることを考えると、ログインユーザのログインIDを取れないのは自然ですが、何か良い方法はないかと模索しています。

お知恵を貸していただけると幸いです。
よろしくお願いいたします。

Message has been deleted

Yasushi Masuda

unread,
Oct 30, 2006, 4:44:40 PM10/30/06
to djan...@googlegroups.com
admin のテンプレートには必ずユーザオブジェクトが渡りますから,テンプレートを
カスタマイズして,ユーザ id の入った隠しタグを挿入するというのはどうでしょう.

まず, myapp/models.py に Hoge が定義されていたとして,
myapp/templates/admin/myapp/hoge/change_form.htmlを作成します.

change_form.html は admin/change_form.html を継承します.admin/change_form には
form_top というブロックがある(これはたぶん django の内部利用ではなく,アプリケーション
開発時用のカスタマイズポイントだと思います)ので,このブロックにデフォルト値のタグを
貼り込みます.

{% extends "admin/change_form.html" %}
{% block form_top %}
<input type="hidden" id="userid_embedded" name="editor" value="{{ user.id }}">
{% endblock %}

自動生成される方の Editor フィールドが目障りなら, class Admin の fields オプションで
抑制できます.

また,Editor フィールドのデフォルト値として自動的に値を入れたいのなら,
userid_embedded から id_editor (Editor フィールドのフォームコントロール) に値を設定
するような JavaScript を作成して, class Admin の js オプションで取り込めばよいと
思います.

--
Yasushi Masuda
http://ymasuda.jp/

Nakane Ryuji

unread,
Oct 30, 2006, 5:26:51 PM10/30/06
to djan...@googlegroups.com
竜@コンプネットです%まだまだ不勉強

06/10/31 に jun<ledmo...@gmail.com> さんは書きました:
>
> モデル定義が、ログインの有無と独立であることを考えると、ログインユーザのログインIDを取れないのは自然ですが、何か良い方法はないかと模索しています。

django.contrib.auth.models.User.id で現在のログインユーザの id
は取れると思います

ログインしているユーザの id と、class Hoge(models.Model) の id
との関係が分からないので、管理画面でユーザの id 云々という意味
がよく分かりません
ログインユーザの id と Hoge の id が等しいと考えて良いなら、
フォームを呼び出す URL に django.contrib.auth.models.User.id
値を組み込んでやれば良いような気もします (←動作未確認)

--
Nakane Ryuji living at Nagoya
// mailto:ryu...@gmail.com
// business http://www.compnet.jp/
// private http://www.bernese.jp/lux/

Nakane Ryuji

unread,
Oct 30, 2006, 5:35:14 PM10/30/06
to djan...@googlegroups.com
竜@コンプネットです

訂正
s/django.contrib.auth.models.User/request.user"/

以下訂正後の全文を再掲

> 06/10/31 に jun<ledmo...@gmail.com> さんは書きました:
> >
> > モデル定義が、ログインの有無と独立であることを考えると、ログインユーザのログインIDを取れないのは自然ですが、何か良い方法はないかと模索しています。
>

> request.user.id で現在のログインユーザの id は取れると思います


>
> ログインしているユーザの id と、class Hoge(models.Model) の id
> との関係が分からないので、管理画面でユーザの id 云々という意味
> がよく分かりません
> ログインユーザの id と Hoge の id が等しいと考えて良いなら、

> フォームを呼び出す URL に request.user.id の値を組み込んでや

Yasushi Masuda

unread,
Oct 30, 2006, 7:22:23 PM10/30/06
to djan...@googlegroups.com
ちょっと試してみて,間違いを見つけました.

> {% extends "admin/change_form.html" %}
> {% block form_top %}

> <input type="hidden" name="editor" value="{{ user.id }}" id="embedded_editor">
> {{ request.POST }}
> {% endblock %}

{% block form_top %} を使うと,その後にある自動生成の
Editor フィールドの値が未設定なために POST データが更新され,バリデーション
エラーになってしまいます.
というわけで,フォームの先頭でなく,末尾の方にあるブロックを探してみたところ,
after_related_objects というブロックがありました.

{% extends "admin/change_form.html" %}
{% block after_related_objects %}
<input type="hidden" name="editor" value="{{ user.id }}" id="embedded_editor">
{% endblock %}

手元ではこれでうまくいきました...が,これでは自動生成のフィールドに何を
設定しても無視されるのでユーザに優しくありません.

class Admin:
fields = (
(None, {
'fields': ('title',), }),)

のようにしてフィールドを非表示にする方がよいようです.


ちなみに, JavaScript を使うやり方を試していたら,もっと奇麗にできました.

{% extends "admin/change_form.html" %}
{% block after_related_objects %}
<script type="text/javascript">
document.getElementById("id_editor").selectedIndex={{ user.id }};
</script>
{% endblock %}

です.いかがでしょう.

Yasushi Masuda wrote:
> admin のテンプレートには必ずユーザオブジェクトが渡りますから,テンプレートを
> カスタマイズして,ユーザ id の入った隠しタグを挿入するというのはどうでしょう.
>
> まず, myapp/models.py に Hoge が定義されていたとして,
> myapp/templates/admin/myapp/hoge/change_form.htmlを作成します.
>
> change_form.html は admin/change_form.html を継承します.admin/change_form には
> form_top というブロックがある(これはたぶん django の内部利用ではなく,アプリケーション
> 開発時用のカスタマイズポイントだと思います)ので,このブロックにデフォルト値のタグを
> 貼り込みます.
>
> {% extends "admin/change_form.html" %}
> {% block form_top %}
> <input type="hidden" id="userid_embedded" name="editor" value="{{ user.id }}">
> {% endblock %}
>
> 自動生成される方の Editor フィールドが目障りなら, class Admin の fields オプションで
> 抑制できます.
>
> また,Editor フィールドのデフォルト値として自動的に値を入れたいのなら,
> userid_embedded から id_editor (Editor フィールドのフォームコントロール) に値を設定
> するような JavaScript を作成して, class Admin の js オプションで取り込めばよいと
> 思います.
>

Yasushi Masuda

unread,
Oct 30, 2006, 8:07:35 PM10/30/06
to djan...@googlegroups.com
度々すみません.まだ,間違えていました...

Yasushi Masuda wrote:
> ちなみに, JavaScript を使うやり方を試していたら,もっと奇麗にできました.
>
> {% extends "admin/change_form.html" %}
> {% block after_related_objects %}
> <script type="text/javascript">
> document.getElementById("id_editor").selectedIndex={{ user.id }};
> </script>
> {% endblock %}
>
> です.いかがでしょう.

SELECT の option の並び順とユーザ id は一致していませんから,これでは正しい
ユーザをピックアップできません.スクリプトを手直ししてみました.

{% extends "admin/change_form.html" %}
{% block after_related_objects %}
<script type="text/javascript">

var i;
var sel = document.getElementById("id_editor");
for (i=0; i<sel.options.length; i++){
if (sel.options[i].value=="{{ user.id }}"){
sel.selectedIndex = i;
}
}
</script>
{% endblock %}

ここまで書いて気づいたんですが,これだと,システムに登録されているユーザの
リストを間接的に取得できてしまいます.うーん.

ledmonster

unread,
Oct 31, 2006, 12:08:35 AM10/31/06
to django-ja
Masuda 様

早速のお返事ありがとうございます。林です。
Model
内で解決することを考えていたので、テンプレートのオーバーライドは目から鱗でした。しかし考えてみれば、当然のやり方ですね。

hidden タグを埋め込む方法、javascript
を用いる方法、両方試してみます。
# Masuda様の回答を読んでいて、「Admin
オプションのjs」が使えそうだと思いましたが、
#
よくよく考えてみると、js内ではテンプレートを記述できないので、
# Admin オプションのjs は静的なもの限定ですね。

> ここまで書いて気づいたんですが,これだと,システムに登録されているユーザの
> リストを間接的に取得できてしまいます.うーん.

こちらの方、よく分かりませんでした。
「User
テーブルを外部キーとして用いた場合に管理画面のリストボックスでユーザ一覧が表示されてしまう」という問題でしょうか。
不特定多数を対象としたようなシステムの場合には、hidden
タグ方式がよさそうですね。

ledmonster

unread,
Oct 31, 2006, 12:16:09 AM10/31/06
to django-ja
竜様

お返事ありがとうございます。林です。

質問の方が説明不足だったのですが、
・ Django で自動生成する管理画面を使いたい
・ editor
というフィールドがあり、データを編集したユーザのuser.id
を自動挿入したい
→ Model
定義をうまく書けば自動挿入される?と模索したが、うまくいかない!
という思考回路でした。

管理者ページのテンプレートを上書きする発想がなかったのですね・・・

ありがとうございます、勉強になりました。

Yasushi Masuda

unread,
Oct 31, 2006, 7:37:26 AM10/31/06
to djan...@googlegroups.com
ledmonster wrote:
> Masuda 様

> よくよく考えてみると、js内ではテンプレートを記述できないので、
> # Admin オプションのjs は静的なもの限定ですね。

js でもいけると思いますよ.ただし,

- JavaScript の置き場所に注意する. JavaScript はページの相対か絶対パスで指定
 するので,実行環境に合わせてファイルを正しい場所に配置せねばならない.
- JavaScript の実行タイミングに注意する.js で指定したスクリプトが差し込まれる
 場所はページの冒頭 (change_form.html の {% include_admin_script_js %}) なので,
 フォームコントロールを読み込んだ後で実行されるように onLoad ハンドラにバインド
 しておく.

のような注意が必要だと思います.

ledmonster

unread,
Nov 8, 2006, 4:35:29 AM11/8/06
to django-ja
林です。

頂いた情報、まだ試せていないのですが、そのまんまの回答がDjango
FAQにありました。
正規の方法はまだないのですね。
http://ymasuda.jp/python/django/docs/faq.html#id46

取り急ぎ、ご報告まで。

Reply all
Reply to author
Forward
0 new messages