2010-07-15 10 views
45

Esta es una pregunta acerca de Python Mixins que podría ser útil en general. Solo estoy usando modelos de Django ya que ese es el caso de uso con el que estoy más familiarizado.Django Model Mixins: hereda de models.Model or from object?

¿Debe una mezcla heredar de la clase está diseñada para mezclarse con o desde 'objeto'?

Ejemplos por código, ¿qué es más correcto o mejor, o mejor dependiendo de lo que quiere lograr?

Este

class TaggingMixin(models.Model): 
    tag = models.ForeignKey(Tag) 

    class Meta: 
     abstract = True 

class MyModel(models.Model, TaggingMixin): 
    title = models.CharField(max_length=100) 

O esto:

class TaggingMixin(object): 
    tag = models.ForeignKey(Tag) 

    class Meta: 
     abstract = True 

class MyModel(models.Model, TaggingMixin): 
    title = models.CharField(max_length=100) 

creo que la herencia de objetos es la manera correcta. Pero estoy viendo ejemplos del primer caso por toda la red ...

EDIT: me he trasladado mi seguimiento pregunta a una pregunta por separado: Django Abstract Models vs simple Python mixins vs Python ABCs

Respuesta

6

Esto parece un trabajo para una abstract model.

EDIT:

Esos no son mixins per se. O más bien, no necesitan serlo. Puede derivar de un modelo abstracto directamente.

+1

Err, sí, tienes razón, este ES un trabajo para un modelo abstracto, de hecho, simplemente los olvidé en el código: s Lo he agregado, pero ahora estoy empezando a confundirme aún más sobre mi propia pregunta ... – hopla

12

Yo recomendaría que herede de object. De esta forma, puede asegurarse de que solo proporcione los métodos y atributos que realmente define explícitamente.

Además, siempre debe asegurarse de poner la clase mixin primero al definir su clase concreta. Las reglas de resolución de Python significan que las superclases se buscan por orden de definición en la declaración de clase, y la resolución se detiene cuando se encuentra un atributo coincidente. Entonces, si tu mixin define un método que también está definido por la superclase principal, no se encontrará tu método de mixin.

+11

Excepto que la magia de metaclase que agrega campos no funciona si tu clase mixin no hereda de 'modelos.Modelo' (o más específicamente, no tiene el' __metaclass__' que se requiere). –

+2

Heredar de objeto no funcionó para mí. Ver: http://stackoverflow.com/questions/17343867/does-south-handle-model-mixins – utapyngo

+2

heredar objeto NO es una buena forma para django. porque django migraciones no pueden reconocerlo. los archivos de migración no contienen los archivados. – 9nix00

3

Cuando hereda de objeto Python llanura del Sur no crea una migración por lo que no puede utilizar este enfoque

+0

No tiene nada que ver con las migraciones del sur. –

+0

Me refiero a que el enfoque no funciona bien con South, que es un gran problema para mí – kharandziuk

45

Django hace mucha magia meta cuando se trata de sus clases del modelo, por lo que lamentablemente el enfoque habitual mezclar como se sugiere en la respuesta de Daniel Roseman, donde heredan de object, no funciona bien en el universo de Django.

La forma correcta de estructurar sus mixins, utilizando el ejemplo proporcionado, sería:

class TaggingMixin(models.Model): 
    tag = models.ForeignKey(Tag) 

    class Meta: 
     abstract = True 

class MyModel(TaggingMixin): 
    title = models.CharField(max_length=100) 

puntos importantes aquí son:

  • Mixins heredan de model.Model pero se configuran como una clase abstracta.
  • Dado que mixins hereda de model.Model, su modelo real debería no heredar de él. Si lo hace, esto podría desencadenar una excepción consistente de orden de resolución de método.
+1

Esto dará como resultado 'TypeError: no se puede crear una orden de resolución de método coherente (MRO)'. Do 'class MyModel (TaggingMixin):' en su lugar. Ver http://stackoverflow.com/q/29214888/1627479 – Joren

+0

Gracias @Joren. Editó la respuesta para reflejar esto. – jsdalton

Cuestiones relacionadas