9

次のような一連のモデルがあります。

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...

これはすべてかなり標準的です。ただし、私がやりたいことは、フィールド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()

これはリモートでも可能ですか?同様の質問がここで尋ねられました。実際には、反復例のコードがいくつか示されていますが、親からプロキシ クラスのインスタンスを取得または作成する方法についてはまだ疑問が残ります。一連のマネージャー メソッドをオーバーライドすることもできると思いますが、それを行うにはもっとエレガントな方法が必要だと思います。

4

2 に答える 2

11

これを行うための「クリーン」または「エレガント」な方法は見つかりませんでした。この問題に遭遇したとき、私は 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

それは本当にきれいではありませんが、私の問題を解決する最も簡単なハックでした。

多分これはあなたを助けるかもしれませんが、そうでないかもしれません。

また、この方法が失敗して戻ってきて私を悩ませるまでの日数を数えているので、他の誰かがこの問題に対するよりPythonicな解決策を持っていることを望んでいます..

于 2013-08-27T20:01:55.313 に答える