gpt4 book ai didi

python - 如何动态地向 Django Model Admin readonly_fields 添加多个字段

转载 作者:太空宇宙 更新时间:2023-11-04 05:27:14 25 4
gpt4 key购买 nike

我有一个用例,我需要检索 Django 模型管理 ListView 中每一行的状态信息。

我可以使用如下代码检索数据:

def blah(admin.ModelAdmin):
@staticmethod
def status(instance):
return Blah(instance).get_info()['status']

readonly_fields = ('id', 'status')

但是,这个“Blah”类会同时返回状态和进度。有没有一种简单的方法可以用实例调用这个“Blah”类,返回状态字段和进度字段,并将两者添加到 readonly_fields 元组而不重复,如:

def blah(admin.ModelAdmin):
@staticmethod
def status(instance):
return Blah(instance).get_info()['status']

@staticmethod
def progress(instance):
return Blah(instance).get_info()['progress']

readonly_fields = ('id', 'status', 'progress')

最佳答案

我想你可以使用类装饰器。

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

关于python - 如何动态地向 Django Model Admin readonly_fields 添加多个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38334958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com