忍者ブログ
Admin / Write / Res
ちゃんとカテゴリ分けされておりませんので、 記事をお探しならブログ内検索が便利です。 ご活用くださいませー+.(≧∀≦)゚+.゚
ブログ内検索
カレンダー
10 2024/11 12
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
カウンター
アクセスカウンター
最新コメント
[11/22 รูปพวงหรีดแสดงความเสียใจ]
[11/22 ดอกไม้ งานศพ]
[11/22 ช่อดอกไม้ตามสั่ง]
[11/22 ร้านดอกไม้บรรยากาศอบอุ่น]
[11/21 Robertret]
最新トラックバック
プロフィール
+ハンドル+
y_ayamori(purple)
+職業+
IT系エンジニア
+すまい+
さいたま
バーコード
[750]  [749]  [748]  [747]  [746]  [745]  [744
djangoのPermissionはわかりにくいですよね。
恐らくやり方だけが出回っているため、その全体像がイメージしにくいために把握に時間が掛かってしまうのだと思います。

私もかなり調べました。
djangoのPermissionの考え方はシンプルでCRUDに基づき、追加・削除・更新・閲覧がデフォルトで用意されています。
そしてその権限はアプリとモデルに紐づくということです。

アプリに紐づくというのはイメージしやすいのですがモデルに紐づくというのがちょっと混乱を招いている気がします。
というのも権限の範囲がアプリというスコープなのはイメージしやすいですが1アプリの中でモデルは複数存在するものではないかと思います。
にもかかわらず権限はモデルに紐づくため、モデルと言ってもどのモデルを使えば…?
という疑問から始まってしまいます。

しかもモデルに紐づけている割にはその仕組みをコンテントタイプ(ContentType)というここにきて新しい概念で括ってきます。
これらの立て付けをちゃんと説明しているサイトが少なく、権限付与のやり方という結論しかないため難しくしているのではないでしょうか。
ちなみにContentTypeはざっくりアプリ名とモデル名を紐づけたものです。

さらにContentTypeはdjangoアプリに。
permission自体はauthアプリに紐づくのもわかりにくい。
ここはもはや標準機能内のおはなしなのでそういうもの、で終わらせておきましょう。

これらから私はdjangoのPermissionsは以下のように立て付けることとしました。
アプリまたは業務スコープ内でPersmissionsテーブルを作ってしまう。
よくあるブログと投票の例でいうと

class BlogPost(models.Model):
    # ...


class Vote(models.Model):
    # ...
こんな感じがあったとしてブログを管理できる権限と管理ができる権限を分ける場合、こんな感じのモデルを作っちゃいます。
class BlogPermission(models.Model):
    class Meta:
        managed = False


class VotePermission(models.Model):
    class Meta:
        managed = False
Permissionはモデル(テーブル)に自動的に自動的に紐づくので、中身や管理も不要です。
managed=Falseでもパーミッションは作成されてしまうようなので、modelsに記載されているかどうかが重要のようです。
またモデルを消してもPermissionは残るので、もしかしたらカスタムPermissionのほうが良いかもしれません…
とはいえ権限の設定があることがmodelsに記載すること明白になるので、まったくメリットがないというわけじゃないと思っています。
なのでここまでできてしまえば、後は簡単。
# 必要なモデル群をimport
from django.contrib.auth.models import User, ContentType, Permission
from sample.models import BlogPermission

# ContentTypeを引き出して、該当の権限を引っ張る
content_type = ContentType.objects.get_for_model(BlogPermission)
permissions = Permission.objects.filter(content_type=content_type)

# それをユーザに紐づけるだけ
user.user_permissions.set(permissions)
if user.has_perm("sample.add_blogpermission"):
    print('権限あります')

# 上記はCRUD全てですが、特定の権限に絞る場合はこんな感じ
permissions = Permission.objects.filter(content_type=content_type, codename__startswith='delete')

次にグループです。
グループの概念がある割にグループに関する操作マニュアルが希薄でこれまたわからない…
どこにグループの作り方の記載あるのでしょうか…
テーブル見る限り、単純にINSERTで対応してしまえばよいみたいです…
ここもキャメルケースにすべきかどうかも不明ですね…
# グループを作成
group = Group(name='BlogAdmin')
group.save()

# グループが持つ権限をセット
permissions = Permission.objects.filter(content_type=content_type)
group.permissions.set(permissions)
group.save()

# ユーザにグループ権限を付与
user.groups.set([group])
慣れればこれだけ。
ただグループとユーザが同列のため、その権限はユーザPermissionなのかグループPermissionなのかはしっかり設計が必要です。

私は権限のスコープはモデルで、権限の塊はグループで分けることにしました。
# 閲覧のみ
group = Group(name='BlogViewer')
group.save()
permissions = Permission.objects.filter(content_type=content_type, codename__startswith='view')
group.permissions.set(permissions)
group.save()

# 編集者
group = Group(name='BlogEditor')
group.save()
group.permissions.set([Permission.objects.get(content_type=content_type, codename__startswith='view'),
                      Permission.objects.get(content_type=content_type, codename__startswith='add'),
                      Permission.objects.get(content_type=content_type, codename__startswith='change'),])
group.save()

少しでも参考になれば幸いです。

拍手

PR
この記事にコメントする
Name
Title
Color
Mail
URL
Comment
Password   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
secret (管理人にのみ表示)
Copyright ©  アナログを愛するデジタル生活館 All Rights Reserved.
* material by Pearl Box   * Template by tsukika

忍者ブログ [PR]