2012-01-04 8 views
7

Ho un modello segue e classe di base astrattaUn modello Django quelle sottoclassi un abc, dà un conflitto metaclasse

import abc 
from django.db import models 


class AbstractBase(): 
    __metaclass__ = abc.ABCMeta 

    @abc.abstractmethod 
    def my_method(self): 
     return 


class MyModel(models.Model, AbstractBase): 
    @abc.abstractmethod 
    def my_method(self): 
     return 1 

Ma sto ottenendo il seguente errore.

conflitto metaclasse: la metaclasse di una classe derivata deve essere un (non-strict) sottoclasse dei metaclassi di tutte le sue basi

Credo che il problema qui è (come è descritto qui http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/) che due classi base hanno due metaclassi differenti, quindi python non può decidere quale metaclasse usare per oggetto figlio.

Al fine di risolvere questo ho tolto ereditarietà multipla e l'uso seguente metodo registro per registrare classe figlia

abc.register(Child) 

ma non ho davvero come questo approccio, poiché sembra scimmia patch.

C'è un altro modo per risolvere questo problema?

Provo ad assegnare metaclasse Model a Child in modo esplicito ma non ha funzionato. Non sto cercando un modo per risolverlo scrivendo il codice. Penso che questo debba essere risolto cambiando la mia struttura di classe.

+0

Penso che dovrai creare un nuovo metaclasse che faccia sia le cose di django che di abc, probabilmente chiamando le loro rispettive metaclassi in ordine, magari usando l'ereditarietà. – cha0site

+0

Non c'è nulla di sbagliato nell'usare il metodo abs.register: è progettato esattamente per questi casi. A proposito, il modo in cui Python pensa alle cose è fatto in modo che raramente si debbano le interfacce _need_ e così via - forse sei troppo limitato dal modo in cui le cose sono fatte in linguaggi statici? – jsbueno

+0

@jsbueno - Potresti avere ragione, ma dovrò implementare la funzionalità dell'interfaccia in qualche modo. Ecco un esempio di impianto- https://gist.github.com/1559689. C'è un modo migliore per implementare questa funzionalità, in python? – yilmazhuseyin

risposta

2

Oltre a creare un nuovo metaclasse che eredita da entrambi ABCMeta e ModelBase, o fare ABCMeta ereditare da ModelBase, non c'è molto che si può fare.

Tuttavia, potrebbe essere appropriato un diverso schema di registrazione? Forse qualcosa come contrib.admin.autodiscover? O un decoratore di classe? O un loop nella parte inferiore del file .py che chiama register nelle classi appropriate (ad esempio, for var in globals().values(): if isinstance(var, type) and issubclass(var, AbastractBase): register(var))?

Modifica: D'oh. Ho pensato che ABCMeta fosse un esempio, non ABCMeta. Questo è quello che ottengo per la navigazione StackOverflow su troppo poco sonno.

+0

La mia conclusione su questo è Se sto usando abc come interfaccia, dovrei usare abc.register. Penso davvero che ci dovrebbe essere un modo migliore per implementare un'interfaccia (http://www.python.org/dev/peps/pep-0245/). Senza di loro, le caratteristiche di Python mi sembrano molto deboli. – yilmazhuseyin

+3

Se ritieni che questo "renda l'OO debole di Python", allora potrei umilmente suggerire che la tua comprensione dei "requisiti per OO forte" differisce drasticamente da quelli dei designer di Python (o che hai digitato accidentalmente "oo" quando intendevi digitare "controllo di tipo statico"?) –

Problemi correlati