私には2つのモデルがあり、1つは従業員で、もう1つは資産であり、資産と従業員の間には多対1の関係があります。また、アセットはStackedInlineフィールドとして従業員管理インターフェイスに追加されます。とにかく、アセットを従業員管理の読み取り専用フィールドにすることはできますか。
私の意図は、従業員が誤って削除しないように、従業員が現在管理者に保持しているすべての資産を表示することでした。
私には2つのモデルがあり、1つは従業員で、もう1つは資産であり、資産と従業員の間には多対1の関係があります。また、アセットはStackedInlineフィールドとして従業員管理インターフェイスに追加されます。とにかく、アセットを従業員管理の読み取り専用フィールドにすることはできますか。
私の意図は、従業員が誤って削除しないように、従業員が現在管理者に保持しているすべての資産を表示することでした。
編集:実際には、これはインラインモデルでは機能しないと思います..
Django は、3 月中旬頃にリリースされる Django 1.1 にネイティブの読み取り専用フィールドを追加する予定です。
読み取り専用管理フィールド( http://www.djangosnippets.org/snippets/937/ )
このスニペットを使用すると、管理画面でフィールドを読み取り専用に設定できます。
このコードを使用して、admin.pyにReadonlyAdminとしてインポートします。これはreadonlyadminの変更された形式です。
from django import forms
from django.utils.safestring import mark_safe
from datetime import datetime
class ReadOnlyWidget(forms.Widget):
def __init__(self, original_value, display_value):
self.original_value = original_value
self.display_value = display_value
super(ReadOnlyWidget, self).__init__()
def render(self, name, value, attrs=None):
if self.display_value is not None:
return unicode(self.display_value)
return unicode(self.original_value)
def value_from_datadict(self, data, files, name):
return self.original_value
#to make fields foreignkey readonly
class ReadOnlyAdminFields(object):
def get_form(self, request, obj=None):
form = super(ReadOnlyAdminFields, self).get_form(request, obj)
if hasattr(self, 'readonly') and obj is not None:
for field_name in self.readonly:
if field_name in form.base_fields:
if hasattr(obj, 'get_%s_display' % field_name):
display_value = getattr(obj, 'get_%s_display' % field_name)()
else:
display_value = None
if getattr(obj, field_name).__class__ in [unicode , long, int, float, datetime, list]:
form.base_fields[field_name].widget = ReadOnlyWidget(getattr(obj, field_name), display_value)
else:
form.base_fields[field_name].widget = ReadOnlyWidget(getattr(obj, field_name).id, display_value)
form.base_fields[field_name].required = False
return form
django-adminにはそのためのフラグはないと思います。詳細については、Djangoブックの第18章を確認してください。テンプレートを手動でハックする必要があります。
おそらく、すべての要素で「無効」に設定されていることを除いて、基本的なフォームであるカスタムウィジェットをフィールドに追加できると思います-ただし、新しいレコードを追加する可能性を削除する方法はわかりません。
従業員のアセットのみを表示したい場合は、デフォルトの django admin change_form.html を変更できます。(また、最初にインラインを無効にすることもできます)
デフォルトの管理テンプレートをオーバーライドするには、管理テンプレート フォルダーをローカルの django テンプレート フォルダー (setting.py の ${TEMPLATE_DIRS}) にコピーします。
そしてchange_form.htmlには、このブロックがあり、
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
これはインラインを表示するために使用され、ここでできることは、現在の従業員の資産のリストなどの追加情報をこのテンプレートにレンダリングし、インラインの元の位置の上に配置することです。
問題は、この追加情報をこのテンプレートにレンダリングするにはどうすればよいかということです。これは、従業員の管理モデルで change_view() 関数をオーバーライドすることで実行できます。
たとえば、admin.py で
class EmployeeAdmin(admin.ModelAdmin):
...
def change_view(self, request, object_id, extra_context=None):
assets = Asset.objects.filter(employee=Employee.objects.get(id=object_id))
context_data = {'inlines': assets, }
return super(EmployeeAdmin, self).change_view(request, object_id, extra_context=context_data)
管理者の change_form.html に戻り、テンプレート タグを使用して、EmployeeAdmin からの extra_context を表示します。
例えば、
{% for inline in inlines %}
{{ inline }}
{% endfor %}
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
これが役に立てば幸いです。これはdjango 1.2.4の場合です