2017-03-20 8 views
3

私はこの例外を取得:DjangoのORM:子クラスのフィールドの上書きrelated_name

class BasePlugin(models.Model): 
    ticket = models.OneToOneField('foobar.ticket', primary_key=True, 
            related_name='%(app_label)s_%(class)s') 

    class Meta(IndexImplementation.Meta): 
     abstract = True 

    # .. Other stuff which should be available for SpecialPlugin 
    # and other child classes. 

class SpecialPlugin(BasePlugin): 
    ticket = models.OneToOneField('foobar.ticket', primary_key=True, 
            related_name='special') 

私だけfound this noteが、私の場合は、親クラスは抽象である:ここでは

django.core.exceptions.FieldError:

Local field 'ticket' in class 'SpecialPlugin' clashes with field of similar name from base class 'BasePlugin'

は私のモデルです。ここに当てはまるかどうかわかりません。

BasePluginの関連する名前(%(app_label)s_%(class)s)が古いコードを壊すので、子クラスSpecialPluginに関連名「special」を付けたいとします。

「特別な」SpecialPlugin.ticketにrelated_nameを与える方法はありますか?これが問題の核心のように見える

+0

このエラーは、親クラスが** abstract **でない場合にのみ発生します。私はちょうどあなたのものに似たシンプルなモデルでテストしたところ、うまく動作します。例外を発生させるDjangoコードを調べると、親クラスが抽象クラスであるかどうかがチェックされます。これは、 'BasePlugin'が抽象として正しく設定されていないことを私に示唆しています。 'IndexImplementation.Meta'には何がありますか? IndexImplementation.Meta @solarissmoke – solarissmoke

+0

は真=抽象的です。だから私はエラーメッセージを理解していないのです。 – guettli

答えて

3

それは醜いハックのように見えるかもしれませんが、あなたの代わりに、文字列のrelated_name引数に関数呼び出しを設定することができます。子クラス/モデルでその関数をオーバーライドします。

class BasePlugin(models.Model): 

    @staticmethod 
    def get_ticket_related_name(): 
     return '%(app_label)s_%(class)s' 

    ticket = models.OneToOneField('foobar.ticket', primary_key=True, 
            related_name=get_ticket_related_name.__func__()) 

    class Meta(IndexImplementation.Meta): 
     abstract = True 


class SpecialPlugin(BasePlugin): 
    @staticmethod 
    def get_ticket_related_name(): 
     return 'special' 
+0

:-(SpecialPluginには、より利用可能ではない私のサブクラスでget_ticket_related_nameが呼び出されることはありません – guettli

+1

あなたは確認していました@kzh – kzh

+0

:1.あなたの基底クラスは抽象です2.サブクラスで 'get_ticket_related_name'方法に出現/宣言の順序を変更すると、それを修正? – v1k45

0

はモデルフィールドのオーバーライドであるDjango model inheritance, overriding fields

問題が ticketフィールドなしクラスへのBasePluginを分離し、その後 ticketフィールドが含まれている子クラスを作成することになりますあなたのための

簡単な回避策

class BaseWithoutTicketPlugin(models.Model): 
    # .. Other stuff which should be available for SpecialPlugin 
    # and other child classes. 
    class Meta(IndexImplementation.Meta): 
     abstract = True 

class BasePlugin(BaseWithoutTicketPlugin): 
    ticket = models.OneToOneField('foobar.ticket', primary_key=True, 
            related_name='%(app_label)s_%(class)s') 

    class Meta(BaseWithoutTicketPlugin.Meta): 
     abstract = True 


class SpecialPlugin(BaseWithoutTicketPlugin): 
    ticket = models.OneToOneField('foobar.ticket', primary_key=True, 
            related_name='special') 

アイデアは、あなたがticketをカスタマイズし、そうでないときBasePluginを使用する必要がある場合BaseWithoutTicketPluginを使用することです。

+0

BasePluginには、必要な他の属性があります。私はそれから継承する必要があります。申し訳ありませんが、私は質問のために私のコードをスト...私は質問を更新する。 – guettli

+0

@guettliそれでも私の提案に問題が表示されていないが、私は私の答えを更新しました。 –

+0

「その他のもの」の部分には属性「チケット」が必要です。つまり、この部分を「BasePlugin」に移動する必要があります。これを実行した後、他の-スタッフ部分は、この答えはよさそうだ – guettli

関連する問題