最近、Djangoを使用して、twisted.webを使用して何年にもわたって有機的に成長した既存の大規模なアプリケーションを管理し始めました。Django自動管理インターフェースと私は結果に非常に満足しています。
私の目的には欠けているように思われることの1つは、ユーザーにデータへの読み取り専用アクセスを許可する機能です。たとえば、ユーザーがログインして注文書を作成できるようにする役割があります。また、他のクライアントや製品のデータを表示できる必要がありますが、編集することはできません。
Django adminで「表示」権限を作成して、ユーザーが他のテーブルへの読み取り専用アクセス権を持ちながら、一部のテーブルのデータを変更できるようにするにはどうすればよいですか?
更新:Django管理者がCRUDインターフェイスのCUDを教えてくれたようです。権限とグループが関連付けられた読み取り専用パーツを取得するにはどうすればよいですか?
2010年2月12日更新:Django 1.2には読み取り専用が含まれるようになりました。詳細は以下のとおりです。
私は自分の質問に答えたと思います。以下の実際の答えにコンテンツを移動します。
管理ビューに読み取り専用フィールドを追加する機能がDjangoバージョン1.2に含まれるようになりました。
チケット番号342を参照 http://code.djangoproject.com/ticket/342
チェンジセット番号11965を参照 http://code.djangoproject.com/changeset/11965
ドキュメントを参照してください http://docs.djangoproject.com/en/dev/ref/contrib/admin/#Django.contrib.admin.ModelAdmin.readonly_fields
これが私がDjango 1.0.2を変更して「表示」権限を追加した方法です。申し訳ありませんが利用可能な差分はありません。
#./contrib/auth/management/__init__.py
def _get_all_permissions(opts):
"Returns (codename, name) for all permissions in the given opts."
perms = []
for action in ('add', 'change', 'delete', 'view'):
perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))
return perms + list(opts.permissions)
run manage.py syncdb
Auth_permissionsテーブルのすべてのテーブルに表示権限が追加されたことを確認しました
モデルクラスにget_view_permissionを追加しました。これは、ファイル./db/models/options.pyにあります。これは、次のステップでadminクラスによって使用されます。
def get_view_permission(self):
return 'view_%s' % self.object_name.lower()
一貫性を保つために、システムに「has_view_permission」を追加します。 contrib/admin/options.pyのどこかにあるはずです。ユーザーが変更権限を持っているかどうかを確認すると、表示権限が自動的に暗示されます。
# /contrib/admin/options.py
# Added has_view_permissions
def has_view_permission(self, request, obj=None):
"""
Returns True if the given request has permission to change or view
the given Django model instance.
If `obj` is None, this should return True if the given request has
permission to change *any* object of the given type.
"""
opts = self.opts
return self.has_change_permission(request, obj) or \
request.user.has_perm(opts.app_label + '.' + opts.get_view_permission())
# modified get_model_perms to include 'view' too.
# No idea where this may be used, but trying to stay consistent
def get_model_perms(self, request):
"""
Returns a dict of all perms for this model. This dict has the keys
``add``, ``change``, and ``delete`` and ``view`` mapping to the True/False
for each of those actions.
"""
return {
'add': self.has_add_permission(request),
'change': self.has_change_permission(request),
'delete': self.has_delete_permission(request),
'view': self.has_view_permission(request),
}
# modified response_add function to return the user to the mode list
# if they added a unit and have view rights
...
else:
self.message_user(request, msg)
# Figure out where to redirect. If the user has change permission,
# redirect to the change-list page for this object. Otherwise,
# redirect to the admin index.
#if self.has_change_permission(request, None):
if self.has_change_permission(request, None) or self.has_view_permission(request, None):
post_url = '../'
else:
post_url = '../../../'
return HttpResponseRedirect(post_url)
# modified the change_view function so it becomes the details
# for users with view permission
#if not self.has_change_permission(request, obj):
if not (self.has_change_permission(request, obj) or (self.has_view_permission(request, obj) and not request.POST)):
raise PermissionDenied
# modified the changelist_view function so it shows the list of items
# if you have view permissions
def changelist_view(self, request, extra_context=None):
"The 'change list' admin view for this model."
from Django.contrib.admin.views.main import ChangeList, ERROR_FLAG
opts = self.model._meta
app_label = opts.app_label
#if not self.has_change_permission(request, None):
if not (self.has_change_permission(request, None) or self.has_view_permission(request, None)):
raise PermissionDenied
Contrib/admin/templates/admin /index.htmlのデフォルトテンプレートを変更しました。これは、代わりにファイルをローカルテンプレートディレクトリにコピーすることでも処理できます。両方に変更を加えたので、後でアップグレードして変更が上書きされた場合にコピーを作成します。
{% for model in app.models %}
<tr>
{% if model.perms.change %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
{% if model.perms.view %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% endif %}
見つかったcontrib/admin/templatetags/admin_modify.pyは、保存/保存および続行ボタンが表示されるかどうかを制御しているようです。 「保存」フィールドをデフォルトの常にTrueから変更し、コンテキストと権限を確認しました。ユーザーが変更または追加のアクセス許可を持っている場合、ユーザーは保存できるはずです。
'show_save': (change and context['has_change_permission']) or (context['add'] and context['has_add_permission'])
Contrib/admin/templatetags /admin_modify.pyを再度変更しました。 'save_as'の意味がわからないので、何かを壊したかもしれませんが、うまくいくようです。
#'show_save_and_add_another': context['has_add_permission'] and
# not is_popup and (not save_as or context['add']) ,
'show_save_and_add_another': not is_popup and
(( change and context['has_change_permission']) or (context['add'] and context['has_add_permission']))
and
(not save_as or context['add']),
ユーザーが「表示」権限と「変更」権限を持っている場合は、何もしません。変更はビューを上書きします。
ユーザーが「変更」なしで「表示」権限を持っている場合は、デフォルトのフォームを変更し、フォーム要素にDISABLEDまたはREADONLY属性を追加します。すべてのブラウザがこれをサポートしているわけではありませんが、私の目的では、ユーザーに適切なブラウザを使用するように要求できます。 無効/読み取り専用の例
すべてのブラウザが「読み取り専用」を尊重しているわけではないため、一部のコントロールを読み取り専用に設定し、他のコントロールを無効に設定していることがわかりました。これにより、ユーザーは必要に応じてテキストコントロールからデータをコピーできます。
#/Django/contrib/admin/templates/admin/change_form.html
{# JavaScript for prepopulated fields #}
{% prepopulated_fields_js %}
</div>
</form></div>
{% if has_view_permission and not has_change_permission %}
<script type="text/javascript">
jQuery('input:text').attr('readonly', 'readonly');
jQuery('textarea').attr('readonly', 'readonly');
jQuery('input:checkbox').attr('disabled', true);
jQuery('select').attr('disabled', true);
jQuery('.add-another').hide();
</script>
{% endif %}
このスニペットは、スーパーユーザーを書き込みアクセス権を持つ唯一のスニペットにします。
class AdminOwn(admin.ModelAdmin):
def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
return self.readonly_fields
#get all fields as readonly
fields = [f.name for f in self.model._meta.fields]
return fields
それは管理者のすぐそこにあります。管理者のユーザーとグループに特定のモデルを追加、変更、削除するための権限を設定できます。
更新:申し訳ありませんが、Wordビューを誤って解釈してDjango "ではなく意味を与えるため、質問を誤解しました。読み取り専用」。adminを使用して読み取り専用にする場合は、少し作業が必要になると思います。 このスレッド を参照してください。JamesBennett(Djangoリリースマネージャー)は次のように述べています。
このリストのアーカイブを検索するとわかるように、これはDjango管理インターフェースがサポートするように設計されているものではないため、ソリューションは完全に独自のコードを作成する必要があります。
そして
Django adminは、「追加」、「変更」、「削除」の3つの権限で動作します。「表示するが変更はしない」権限がないため、このような権限を適用する方法はありません。重要なカスタムコーディングを行わずに制限。
追加の作業には、特定のモデルに「読み取り専用」権限を追加し、基本的な管理テンプレートを変更して、ユーザーがその権限を持っているかどうかを確認する必要があります。持っている場合は、特定のコントロール(保存ボタンなど)を無効にし、他のコントロールを読み取り専用にします。 。これにより、さりげなくいじくり回すのを防ぐことができますが、サーバー側のロジックを変更して同じアクセス許可を確認し、アクセス許可を回避するために卑劣な方法でPOSTが行われるのを防ぐ必要がある場合もあります。
モデルに「読み取り専用」権限を作成し、jasucaのコードを変更して使用できます。
models.py:
class MyModel(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=256, null=True, blank=True)
class Meta:
permissions = (
('readonly_mymodel','Readonly MyModel'),
)
admin.py:
class MyModelAdmin(admin.ModelAdmin):
def get_readonly_fields(self, request, obj=None):
if not request.user.is_superuser and request.user.has_perm('mymodel.readonly_mymodel'):
return [f.name for f in self.model._meta.fields]
return self.readonly_fields
アプリケーションの管理者では、ユーザーに「変更」と「読み取り専用」の許可を与える必要があります。
Authモジュールでグループを作成できます。次に、ユーザーグループのログインに基づくadmin.pyで、modeladminのreadonly_fields属性を設定します。メソッドdefhas_add_permission(self、request)を追加して、読み取り専用権限を持つグループに対してfalseを返します。グループに追加、変更のアクセス許可を与えます。モデル属性のみを読み取ることができます。