2016-11-02 7 views
4

私は多かれ少なかれ、あなたにとっては不名誉でハックな質問があると思います。私が現在持っているのは、複数のアプリケーションを持つdjangoプロジェクトです。 1つのアプリ(app1)のnon-abstract model (ModelA)を使用し、別のアプリ(app2)でそれをサブクラス化して使用します。 App1のモデル をDBに移行しないでください。機能とロジックを拡張して、app1の機能とモデルクラスを使いたいだけです。 私は両方のアプリケーションをsettings.INSTALLED_APPSに追加し、app1のモデルをDBに移行させないようにしました。抽象的な非抽象的なジャンゴモデルを抽象的に動的に作成する方法は?

これまで
INSTALLED_APPS += (
    'App1', 
    'App2', 
) 

# This is needed to just use App1's models 
# without creating it's database tables 
# See: http://stackoverflow.com/a/35921487/1230358 
MIGRATION_MODULES = { 
    'App1': None, 
} 

(MODELA)残りの問題は、APP1のモデルのほとんどが非抽象的であるということになりました...私は知っているので、良い醜いとハックと私はそれらをサブクラス化する をしようとした場合、のいずれもModelAのフィールドはdbにテーブルapp2_modelbに入力されます。 App1を からDBに移行して除外したため、app1_modelaテーブルが完全にDBにないため、これは明らかです。

私の考えは、ModelAをクローンし、その機能性をすべて保持し、メタ情報を非抽象から抽象に変更することでした(ModelB.Meta.abstract = True)。 これにより、ModelAの元のフィールドはすべてModelBに継承され、それぞれのDBテーブルとカラム(app1_modelb)にあります。

私が今持っていることは次のとおりです。

# In app1 -> models.py 
class ModelA(models.Model): 
    title = models.CharField(_('title'), max_length=255) 
    subtitle = models.CharField(_('subtitle'), max_length=255) 

    class Meta: 
     abstract = False # just explicitly for demonstration 


# In app2 -> models.py 
from app1.models import ModelA 

class ModelB(ModelA): 
    pass 
    # Just extending ModelAdoes not create the fields title and subtitle fields in app2_modelb 
    # because ModelA.meta.abstract = False 

私の現在の方法(擬似コード)既存の非抽象モデルの抽象は次のように見えるようにする:

# In app2 -> models.py 
from app1.models import ModelA 

def get_abstract_class(cls): 
    o = dict(cls.__dict__) 
    o['_meta'].abstract = True 
    o['_meta'].app_label = 'app2' 
    o['__module__'] = 'app2.models' 

    #return type('Abstract{}'.format(cls.__name__), cls.__bases__, o) 
    return type('Abstract{}'.format(cls.__name__), (cls,), o) 

ModelB = get_abstract_class(ModelA) 

class ModelC(ModelB): 
    # title and subtitle are inherited from ModelA 
    description = models.CharField(_('description'), max_length=255) 

これは動作しません、この長い説明の後で、私の(単純な)質問は、すべての機能を保持している非抽象モデルクラスを抽象化する方法とそれをどのようにしてクローンすることが可能なのでしょうか?

上のすべてのファズについては、私はapp1の任意のコードを変更することはできませんについてです。 app1がpip経由でインストールされたdjangoアプリであるかもしれません。

+0

誰かがModelAのインスタンスを作成することを禁止する意思はありますか?とにかくあなたがModelAクラスであれば、model saveメソッドでエラーを発生させる可能性があります。 – Sayse

+0

新しいフィールドを追加しますか? –

+0

意図は以下の通りです。私が私の所有物(app2)のために非常に有用であると思うdjango-blogアプリケーション(app1とModelA)のいくつかのモデルを再利用したいとしましょう。残念なことに、app1.model.ModelAは抽象型ではありません。django-blogアプリケーションでは抽象型である必要はないため、app1内部ではfinal - modelクラスなので、抽象型ではありません。私のアプリ(app2)で使用したい場合は、抽象クラスでサブクラス化でき、すべてのフィールド(ModelAのフィールドも)がテーブル(app2_modelb)で生成されるようにする必要があります。全体としては、もともと再利用を意図していない非抽象モデルの再利用についてです。 – hetsch

答えて

0

なぜ、APP1 APP2で

AbstractBaseModelA(models.Model): 
    # other stuff here 
    class Meta: 
     is_abstract=True 


ModelA(AbstractBaseModelA): 
    # stuff 

中:

MobelB(AbstractBaseModelA): 
    # stuff 

申し訳ありませんが、私はあなたの目的を誤解してきましたが、私は上記と同じ最終結果を達成すべきだと思います。

+0

また、 'issubclass(ModelB、ModelA)'は重要ですか? – nimasmi

+0

私はapp1のコードを変更することはできません.app1はpip経由でインストールされたdjangoアプリだと考えてください。私はこの不明を残して申し訳ありません! – hetsch

+1

これは哲学かプログラミングかわかりませんが、後者の場合:オープンソースなので変更できます。おそらく、パッチを作成してパッチを作成するためのgitまたは同様のソースリポジトリがあります。他の質問は、それが賢明かどうかです。 app1を破る可能性の低いこのような変更については、それが受け入れられるかもしれません。 "上流"の開発者に、モデルが抽象であるべきであることをあなたが有用であると考えていることを納得させることができれば、さらに多くの人が同様にそうかもしれません。どのような場合には、あなたのアイデアを次のリリースに組み込むことができます。 – nigel222

関連する問題