2012-10-08 20 views
8

Estaba teniendo un problema similar al de How to query abstract-class-based objects in Django? El hilo sugiere usar multi_table_inheritance. Yo personalmente creo que el uso de content_type conceptualmente más cómodo (sólo se siente más cerca de la lógica, al menos para mí)Django: using ContentType vs multi_table_inheritance

Utilizando el ejemplo en el enlace anterior, me acaba de añadir un StelarType como

class StellarType(models.Model): 
    """ 
    Use ContentType so we have a single access to all types 
    """ 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

A continuación, agregue este para el modelo base abstracta

class StellarObject(BaseModel): 
    title = models.CharField(max_length=255) 
    description = models.TextField() 
    slug = models.SlugField(blank=True, null=True) 
    stellartype = generic.GenericForeignKey(StellarType) 
    class Meta: 
     abstract = True 

sincronizar entre StellarObject y StellarType, podemos conectar la señal post_save para crear una instancia de StellarType cada vez que se crea un planeta o una estrella. De esta manera, puedo consultar StellarObjects a través de StellarType. Entonces me gustaría saber cuál es el PRO y el CON de usar este enfoque contra el uso de multi_table_inheritance? Creo que ambos crean una tabla adicional en el databse. ¿Pero qué hay del rendimiento de la base de datos? ¿Qué tal usabilidad/flexibilidad? ¡Gracias por cualquiera de tus comentarios!

Respuesta

5

Para mí, ContentType es el camino a seguir cuando quieres relacionar un objeto con uno de muchos modelos que no son fundamentalmente del mismo "tipo". Por ejemplo, si desea poder introducir Comentarios a Usuarios, Páginas e Imágenes en una red social, pero esos tres modelos no comparten un supertipo razonable. Claro que podrías crear un supertipo "Commentable", pero para mí eso se siente más como un mixin que un tipo fundamental del cual derivan esas tres cosas. Antes de que se publicara ContentType, no habría tenido más remedio que inventar supertipos para este tipo de relaciones, lo que puede ponerse muy feo rápidamente si necesita hacerlo varias veces en la misma aplicación (digamos que también tiene Eventos, Alertas, Mensajes, etc., cada uno de los cuales puede aplicarse a un conjunto diferente de modelos).

La herencia de múltiples tablas tiene más sentido cuando desea adjuntar atributos al modelo base, de modo que se compartirán en todos los modelos concretos que se extienden desde él, de modo que pueda obtener un comportamiento polimórfico. Commentable no se ajusta realmente a este molde, porque todo ese comportamiento se puede poner en el modelo de Comentario, y menos en los objetos Commentables. Pero si tiene diferentes clases de usuarios que comparten gran parte del mismo comportamiento y deben ser agregables, entonces tiene mucho más sentido.

El principal pro de la herencia de varias mesas para mí es un modelo de datos más limpio, con relaciones implícitas y la herencia que pueden ser aprovechadas en el lado de Python (polimorfismo es todavía un poco desordenado, sin embargo, como se ve here y here) . El mayor profesional de ContentType es que es más general y mantiene la funcionalidad auxiliar fuera de sus modelos, a costa de un poco un esquema menos prístino (muchos campos "meta" en sus modelos para definir estas relaciones). Y para su ejemplo, todavía tiene que confiar en post_save, lo cual también me parece innecesariamente desordenado/mágico.

+0

Tengo la misma opinión sobre el uso de ContentTypes framework para cosas que no están relacionadas, pero me siento un poco incómodo al usar la herencia Multi-table.Tratando de ser guiado en el mundo de las mejores prácticas, he leído en el libro de Pydanny (2 cucharadas) que la mesa múltiple es malvada. La pregunta final es: ¿Eficiencia o Elegancia? – lborgav

+2

I * love * Two Scoops, pero la amonestación general contra la herencia de mesas múltiples que realmente no entiendo. Solo tiene que comprender las consultas que se generarán para su aplicación y si representan un problema. Si puede hacer la mayor parte de su trabajo en la tabla de supertipos, entonces es especialmente no problemático. No puedo pensar por qué consultar una tabla de supertipos y unirme a subtipos debería ser peor que hacer lo mismo con una tabla ContentType genérica, desde el punto de vista del rendimiento. Puedo ver por qué querría evitar una jerarquía de tipo realmente compleja ... – acjay

+1

Estoy de acuerdo con usted. Y buscando una forma agradable de manejar esto, acabo de encontrar esta aplicación (django-model-utils) que parece ser muy útil: [InheritanceManager] (https://django-model-utils.readthedocs.org/en/ latest/managers.html) – lborgav

0

Lo siento por revivir el hilo viejo. Creo que todo se reduce a la dirección de búsqueda. Si busca todas las subclases para un FK determinado (herencia múltiple) o define la clase referenciada como un tipo de contenido y la busca basándose en la referencia de la tabla y el id (contenttypes) no hace una gran diferencia en el rendimiento - sugerencia: ambos apestan. Creo que los tipos de contenido son una buena opción si desea que su aplicación sea fácilmente ampliable, es decir, otros pueden agregar nuevos tipos de contenido para hacer referencia. Multitable es bueno si solo necesita algunas veces las columnas adicionales definidas en tablas adicionales. A veces también puede ser una buena idea fusionar todos sus subtipos y hacer solo uno que tenga unos pocos campos vacíos la mayor parte del tiempo.