我有一系列看起来像这样的模型:
class Analysis(models.Model):
analysis_type = models.CharField(max_length=255)
def important_method(self):
...do stuff...
class SpecialAnalysis(Analysis):
class Meta:
proxy = True
def important_method(self):
...something different...
Run Code Online (Sandbox Code Playgroud)
这都非常标准.但是,我想要做的是Analysis根据analysis_type字段的值自动将模型转换为代理模型.例如,我希望能够编写如下代码:
>>> analysis = Analysis.objects.create(analysis_type="nothing_special")
>>> analysis.__class__
<class 'my_app.models.Analysis'>
>>> analysis = Analysis.objects.create(analysis_type="special")
>>> analysis.__class__
<class 'my_app.models.SpecialAnalysis'>
>>> analysis = Analysis.objects.get(pk=2)
>>> analysis.__class__
<class 'my_app.models.SpecialAnalysis'>
>>> # calls the ``important_method`` of the correct model
>>> for analysis in Analysis.objects.all():
... analysis.important_method()
Run Code Online (Sandbox Code Playgroud)
这甚至可以远程实现吗?这里提出了一个类似的问题,它实际上为迭代示例提供了一些代码,但是它仍然存在如何从其父代获取或创建代理类实例的问题.我想我可以覆盖一堆管理器方法,但我觉得必须有更优雅的方法来实现它.
EWi*_*Wit 10
我没有找到"干净"或"优雅"的方式来做到这一点.当我遇到这个问题时,我通过欺骗Python来解决它.
class Check(models.Model):
check_type = models.CharField(max_length=10, editable=False)
type = models.CharField(max_length=10, null=True, choices=TYPES)
method = models.CharField(max_length=25, choices=METHODS)
'More fields.'
def __init__(self, *args, **kwargs):
super(Check, self).__init__(*args, **kwargs)
if self.check_type:
map = {'TypeA': Check_A,
'TypeB': Check_B,
'TypeC': Check_C}
self.__class__ = map.get(self.check_type, Check)
def run(self):
'Do the normal stuff'
pass
class Check_A(Check):
class Meta:
proxy = True
def run(self):
'Do something different'
pass
class Check_B(Check):
class Meta:
proxy = True
def run(self):
'Do something different'
pass
class Check_C(Check):
class Meta:
proxy = True
def run(self):
'Do something different'
pass
Run Code Online (Sandbox Code Playgroud)
它不是很干净,但它是最容易找到解决我的问题的黑客.
也许这对你有所帮助,也许它没有.
我也希望别人对这个问题有一个更加pythonic的解决方案,因为我正在计算直到这种方法失败并回来困扰我的日子.
这是一个很好的方法,我并不特别认为它是作弊.这是IMHO对__init__函数的一些增强功能,因此在添加更多类时不必更改.
def __init__(self, *args, **kwargs):
super(Analysis, self).__init__(*args, **kwargs)
if not self.__type and type(self) == Analysis:
raise Exception("We should never create a base Analysis object. Please create a child proxy class instead.")
for _class in Analysis.__subclasses__():
if self.check_type == _class.__name__:
self.__class__ = _class
break
def save(self, **kwargs):
self.check_type = self.__class__.__name__
super(Analysis, self).save(**kwargs)
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
1874 次 |
| 最近记录: |