我已经定义了一些看起来像这样的模型:
class ABClass(models.Model):
#common attributes
class Meta:
abstract = True
class ConcreteClass1(ABClass):
#implementation specific attributes
class ConcreteClass2(ABClass):
#implementation specific attributes
class ModifiedConcreteClass1(ConcreteClass1):
#implementation specific attributes
Run Code Online (Sandbox Code Playgroud)
我有一个视图,它采用'type'参数,指定要显示的类的类型.如果'type = None',我想显示ABClass的所有后代(在本例中为ConcreteClass {1,2},ModifiedConcreteClass1).我在文档中搜索过,似乎无法找到一种不需要维护ConcreteClasses列表的方法.ABClass.__subclasses__()看起来很有希望,但是当我打电话时它会返回一个空列表.
目前我最好的策略是在models.py中创建一个CLASS_LIST变量,该变量在运行时使用inspect方法填充ABClass的所有后代.有没有办法使用django api做到这一点?
谢谢
如果你有的话'django.contrib.contenttypes',已经维护了一个ConcreteClasses列表INSTALLED_APPS.
我是这样做的:
class GetSubclassesMixin(object):
@classmethod
def get_subclasses(cls):
content_types = ContentType.objects.filter(app_label=cls._meta.app_label)
models = [ct.model_class() for ct in content_types]
return [model for model in models
if (model is not None and
issubclass(model, cls) and
model is not cls)]
class ABClass(GetSubclassesMixin, models.Model):
pass
Run Code Online (Sandbox Code Playgroud)
当你需要一个子类列表时,只需要调用ABClass.get_subclasses().
我使用它与具体的基类,但我没有看到这个不与抽象的一起工作的原因.
即使您的具体子类位于不同的Django应用程序中,此方法仍然有效.但请注意,它们app_label应与基类相同,因此代码get_subclasses()可以找到它们.
我没有看到当你在后端设置抽象True时Django做了什么,但是我玩了这个,我发现这个有效.请注意,它仅适用于Python 2.6
from abc import ABCMeta
class ABClass():
__metaclass__ = ABCMeta
class ConcreteClass1(ABClass):
pass
class ConcreteClass2(ABClass):
pass
print ABClass.__subclasses__()
Run Code Online (Sandbox Code Playgroud)
结果是
[<class '__main__.ConcreteClass1'>, <class '__main__.ConcreteClass2'>]
Run Code Online (Sandbox Code Playgroud)
不使用ABCMeta __metaclass__,您将收到一个空列表.
你可以在这里阅读一些很好的描述.只有这个问题,我不确定它是否会影响你是我无法弄清楚为什么当我创建一个ABClass的实例时,它找不到子类.也许通过玩一下并阅读更多的文档,它可能会让你在某个地方.
让我知道这对你有什么用,因为我对真正的答案真的很好奇.
看看这个类似的问题:
我的解决方案基本上是这样的:
def get_children(self):
rel_objs = self._meta.get_all_related_objects()
return [getattr(self, x.get_accessor_name()) for x in rel_objs if x.model != type(self)]
Run Code Online (Sandbox Code Playgroud)
虽然那里还有许多其他好的解决方案.您实际上可能想要基类的子项,而不仅仅是子类.如果没有,那里的答案可以作为您解决方案的动力.
| 归档时间: |
|
| 查看次数: |
4821 次 |
| 最近记录: |