をクラスデコレータを使用することができます。
def get_blah_info(field):
return staticmethod(lambda x: Blah(x).get_info()[field])
def blah_decorator(*fields):
def wrapper(cls):
for field in fields:
setattr(cls, field, get_blah_info(field))
cls.readonly_fields.append(field)
return cls
return wrapper
@blah_decorator('status', 'progress')
class BlahAdmin(admin.ModelAdmin):
readonly_fields = ['id']
しかし、静的メソッドを使用している理由はわかりません。
より高度な例:もちろん
from django.utils.translation import ugettext_lazy as _
def get_blah_info(blah_class, field):
def get_info(self, instance):
return blah_class(instance).get_info()[field]
return get_info
def blah_decorator(blah_class, **fields):
def wrapper(cls):
# Make sure readonly_fields is a list so that we can append elements
readonly_fields = getattr(cls, 'readonly_fields', [])
if not hasattr(readonly_fields, 'append'):
readonly_fields = list(readonly_fields)
for field, short_description in fields.items():
# Define the method for each field and append it to readonly_fields
get_info = get_blah_info(blah_class, field)
get_info.__name__ = field
get_info.short_description = short_description
setattr(cls, field, get_info)
readonly_fields.append(field)
cls.readonly_fields = readonly_fields
return cls
return wrapper
@blah_decorator(Blah, status=_("Status"), progress=_("Progress"))
class BlahAdmin(admin.ModelAdmin):
readonly_fields = ['id']
、上記の例では、あなたが好む場合は、静的メソッドを使用するように適合させることができます。
別の解決策は、metaclassを使用することです。
class BlahMetaclass(type):
@staticmethod
def get_blah_info(blah_class, field):
def get_info(self, instance):
return blah_class(instance).get_info()[field]
return get_info
def __new__(cls, cls_name, bases, attrs):
blah_class = attrs['blah_class']
blah_fields = attrs['blah_fields']
readonly_fields = attrs.get('readonly_fields', [])
if not hasattr(readonly_fields, 'append'):
readonly_fields = list(readonly_fields)
for field, short_description in blah_fields:
if field in attrs:
continue # Let the class have the precedence
get_info = cls.get_blah_info(blah_class, field)
get_info.__name__ = field
get_info.short_description = short_description
attrs[field] = get_info
if field not in readonly_fields:
# Do not add `field` to `readonly_fields` if it is already present.
# This enables to redefine the fields order rather than
# appending `blah_fields`.
readonly_fields.append(readonly_fields)
attrs['readonly_fields'] = readonly_fields
# Optionally remove `blah_class` and `blah_fields` if
# not useful any further.
del attrs['blah_class']
del attrs['blah_fields']
return super().__new__(cls, clsname, bases, attrs)
class BlahModelAdmin(admin.ModelAdmin, metaclass=BlahMetaclass):
"""Optionally, create a new base ModelAdmin."""
class BlahAdmin(BlahModelAdmin):
blah_class = Blah
blah_fields = [
('status' _("Status")),
('progress', _("Progress")),
]
readonly_fields = ['id']
# Or, for instance: readonly_fields = ['status', 'id', 'progress']
# If you want to change the order
なぜ静的メソッドを使用していますか? –
彼らは静的である必要はありませんでした。私はそれらを通常の方法にする必要はありませんでしたが、それらを変更する問題はありません。 – Mike91
そうですが、 'self'を使用しない場合、それらがインスタンスメソッドである必要はありません。しかし、私はこれらのメソッドをインスタンス化するために使用されているので、少し混乱していました。 :) –