田中さん

おやりになりたいことが以下のことだとしますね。

・ユーザが以下のグループに所属している。
Group A: arthur, lancelot
Group B: galahad, robin
Group C: arthur, boas, gawain
Group D: vedevire, kay
・ユーザ arthur は A と C に属するユーザしかAdminで操作できない

素直にやると、こんな感じです。

user = request.user
available_user_ids = []
for group in user.groups.all():
  group_user_ids = [u.id for u in group.user_set.all()]
  available_user_ids.extend(group_user_ids)
qs = qs.filter(id__in=available_user_ids)

もしくは
from itertools import chain

qs = qs.filter(id__in=
  list(chain(*([u.id for u in g.user_set.all()] for g in
request.user.groups.all()))))

ただ、これではあんまりなので、次のように考えてもいいかも。

・arthur の属するグループは arthur.group.all() で取れます。→ group_a, group_c
・group_c の属するユーザのクエリセットは group_c.user_setです。
・表示したいユーザは group_a か group_c に属していればいいので、group_a.user_set と
group_c.user_set の OR です。
・複数のグループに重複するユーザがいると、結果セットにもユーザが重複して出ますから、 distinct を取る必要があります。

従って、以下でどうでしょう。
from django.db.models import QuerySet
qs = reduce(QuerySet.__or__, (g.user_set.all() for g in
u.groups.all()), User.objects.none()).distinct()

このクエリセットは以下のような SQL を発行します。

SELECT DISTINCT
  "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
  "auth_user"."is_superuser", "auth_user"."username",
  "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email",
  "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined"
FROM
  "auth_user"
  INNER JOIN "auth_user_groups"
  ON ( "auth_user"."id" = "auth_user_groups"."user_id" )
WHERE ("auth_user_groups"."group_id" = <グループAのid> OR
"auth_user_groups"."group_id" = <グループCのid>)

ユーザの属しているグループが増えると、 WHERE 句の OR 条件が増えていきます。
従って、何万もグループが生成される場合、全てのグループに属するユーザを作ってしまうと、そのユーザだけ、Adminアクセス時に大きなSQL文が生成されるので注意してください。



2016年4月22日 13:35 Jun Tanaka <tna...@gmail.com>:
> 増田様、
>
> ご指導いただき誠に有難う御座います。
>
> class MyModelAdmin(admin.ModelAdmin):
>     def get_queryset(self, request):
>         qs = super(MyModelAdmin, self).get_queryset(request)
>         if request.user.is_superuser:
>             return qs.filter(xxx=request.user.groups.all())
>
>         return qs.filter(author=request.user)
>
>
> 多分、こんな感じかなっていうところまでは分かりました。
> 上記のxxxにあたる部分を分かりませんでしょうか?
>
> この様な形で実装できればグループA~Dある場合に、
> superuserにグループA+グループBも編集できC,Dはできないとできるので非常に有難いと思います。
>
> 宜しくお願い致します。
>
>
> 2016年4月21日木曜日 0時00分45秒 UTC+9 Yasushi Masuda:
>>
>> 田中さん
>>
>> まず、管理者の所属グループで、ユーザ一覧を絞り込む方法。
>>
>>
>> http://stackoverflow.com/questions/12354099/override-default-queryset-in-django-admin
>>
>> のアンサーのように、 get_queryset をオーバライドして、管理画面にログインしているユーザ(管理者)を reqeust.user
>> から特定して、そのユーザーがどのグループに属しているかを調べ、同じグループのユーザーをフィルタして返してください。
>>
>> 次に、AdminSite からデフォルトのユーザのAdminを Unregisterして、上で作ったAdminと差し替えます。
>>
>> Adminの枠組みに従っている場合、オブジェクトは全て get_queryset() の返すクエリセットを使って取り出されるため、少なくとも
>> Admin 上ではグループ外のユーザへのアクセスは防げます。
>>
>> ただし、アクセスを制限しているのはAdminの機能であって、ユーザモデル自体のアクセス制御はかかっていないことを忘れないで下さい。
>>
>> 管理画面以外でも、何らかの形で(例えば、「ドキュメントの最終編集ユーザ」のように、別のモデルインスタンスのリレーションからユーザを辿れる場合)他のユーザの情報を見たり編集したりする画面を用意するつもりなら、そこでもグループ外のユーザにアクセスできないよう、制約を設けてやらねばなりません。
>>
>> いかがでしょう?
>>
>> 2016年4月20日 11:06 Jun Tanaka <tna...@gmail.com>:
>> > 田中と申します。
>> >
>> > djangoの管理画面から、グループの管理者みたいなものを作りたいのですが出来そうでできないので質問させていただきます。
>> >
>> > グループA グループBがありそれぞれのグループには複数のユーザーがいます。
>> > データはユーザーごとに仕切られていて他の人は見れません。
>> >
>> > その様な状況でグループAの管理者はグループAのみのユーザーのデータを見れかつ編集できるようにしたい。
>> > (グループBも同様に、)
>> > こんな方法ってありませんか?
>> >
>> > 何かモデル用のモジュールを入れたら出来るのではないかとも考えています。
>> >
>> > ご存知の方がいましたらご教授願えれば幸いです。
>> > 宜しくお願い致します。
>> >
>> > --
>> > --
>> > ----------------- http://djangoproject.jp/ -----------------
>> > You received this message because you are subscribed to the Google
>> > Groups
>> > "django-ja" group.
>> > To post to this group, send email to djan...@googlegroups.com
>> > To unsubscribe from this group, send email to
>> > django-ja-...@googlegroups.com
>> > For more options, visit this group at
>> > http://groups.google.com/group/django-ja
>> > ---
>> > このメールは Google グループのグループ「django-ja」に登録しているユーザーに送られています。
>> > このグループから退会し、グループからのメールの配信を停止するには django-ja+...@googlegroups.com
>> > にメールを送信してください。
>> > その他のオプションについては https://groups.google.com/d/optout にアクセスしてください。
>>
>>
>>
>> --
>> Yasushi Masuda PhD
>> http://whosaysni.jp/
>> whosaysni at twitter/gmail
>
> --
> --
> ----------------- http://djangoproject.jp/ -----------------
> You received this message because you are subscribed to the Google Groups
> "django-ja" group.
> To post to this group, send email to django-ja@googlegroups.com
> To unsubscribe from this group, send email to
> django-ja-unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/django-ja
> ---
> このメールは Google グループのグループ「django-ja」に登録しているユーザーに送られています。
> このグループから退会し、グループからのメールの配信を停止するには django-ja+unsubscr...@googlegroups.com
> にメールを送信してください。
> その他のオプションについては https://groups.google.com/d/optout にアクセスしてください。



-- 
Yasushi Masuda PhD
http://whosaysni.jp/
whosaysni at twitter/gmail

-- 
-- 
-----------------                       http://djangoproject.jp/                
         -----------------
You received this message because you are subscribed to the Google Groups 
"django-ja" group.
To post to this group, send email to django-ja@googlegroups.com
To unsubscribe from this group, send email to 
django-ja-unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/django-ja
--- 
このメールは Google グループのグループ「django-ja」の登録者に送られています。
このグループから退会し、グループからのメールの配信を停止するには django-ja+unsubscr...@googlegroups.com 
にメールを送信してください。
その他のオプションについては、https://groups.google.com/d/optout にアクセスしてください。

メールによる返信