2012-01-20 11 views
8

Tengo este escenario de caso de uso: hay lugares que son parques infantiles, restaurantes, teatros, pubs. la misma place puede tener parques infantiles, restaurantes, teatros, etc. hay un par de maneras de aplicarlo:¿Qué es mejor: claves extranjeras o herencia de modelo?

  1. uso de claves externas

    class Place(models.Model): 
        name = models.CharField(max_length=50) 
    
    class PlayGrounds(models.Model) 
        field1 = models.CharField(max_length=50) 
        place = models.ForeignKey(Place) 
    
  2. herencia de varias tablas

    class Place(models.Model): 
        name = models.CharField(max_length=50) 
        address = models.CharField(max_length=80) 
    
    class Restaurant(Place): 
        serves_hot_dogs = models.BooleanField() 
        serves_pizza = models.BooleanField() 
    
  3. use la clase abstracta

    class Place(models.Model): 
        name = models.CharField(max_length=50) 
    
    class PlayGrounds(Place) 
        field1 = models.CharField(max_length=50) 
        place = models.ForeignKey(Place) 
        class Meta: 
         abstract = True 
    
  4. modelos de uso del proxy

    class Place(models.Model): 
        name = models.CharField(max_length=50) 
    
    class PlayGrounds(Place) 
        field1 = models.CharField(max_length=50) 
        place = models.ForeignKey(Place) 
        class Meta: 
         proxy = True 
    

¿Cuáles son los pros y los contras del uso de cada enfoque?

+0

Necesita decirnos más sobre lo que está haciendo con estos objetos y clases antes de poder ayudarlo. – Marcin

+0

Bueno, si le das un vistazo, solo quería preguntar qué método de implementación es el preferido y en qué lugar? esto es más una cuestión arquitectónica. – whatf

+0

La pregunta "arquitectónica" no puede responderse en abstracto. – Marcin

Respuesta

14

La primera de ellas es herencia esencialmente modelo, porque eso es lo que utiliza la aplicación de MTI de Django (excepto que es un OneToOneField en lugar de un ForeignKey, pero eso es simplemente una ForeignKey que es único).

Cada vez que tenga una relación es-a (es decir,, un restaurante es un lugar), se trata de herencia, por lo que el camino a seguir es utilizar una de las metodologías de herencia modelo de Django. Cada uno, sin embargo, tiene sus pros y contras:

modelos abstractos

modelos abstractos son útiles cuando lo que desea es sin carga campos y/o métodos repetitivos. Se usan mejor como mixins, más que como verdaderos "padres". Por ejemplo, todos estos modelos tendrán una dirección, por lo que la creación de un modelo abstracto Address y tener cada herencia de eso podría ser una cosa útil. Pero, un Restaurant no es un Address, per se, por lo que esta no es una verdadera relación padre-hijo.

MTI (Herencia de tablas múltiple)

Este es el uno que es similar a su primera opción anterior. Esto es más útil cuando necesita interactuar con las clases padre e hijo y los hijos tienen campos únicos propios (campos, no métodos). Entonces, un Restaurant podría tener un campo cuisine, pero un Place no lo necesitaría. Sin embargo, ambos tienen una dirección, por lo que Restaurant hereda y se genera a partir de Place.

modelos sustitutos

modelos sustitutos son como alias. No pueden tener sus propios campos, solo obtienen los campos de los padres. Sin embargo, pueden tener sus propios métodos, por lo que son útiles cuando necesita diferenciar tipos de la misma cosa. Por ejemplo, podría crear modelos proxy como StaffUser y NormalUser desde User. Todavía hay una sola tabla de usuarios, pero ahora puedo agregar métodos únicos para cada uno, crear dos vistas administrativas diferentes, etc.

Para su escenario, los modelos proxy no tienen mucho sentido. Los hijos son intrínsecamente más complicados que los padres y no tendría sentido almacenar todos los campos como cuisine para Restaurant en Place.

Usted podría utilizar un modelo abstracto Place, pero entonces se pierde la capacidad para ponerse a trabajar Place por sí sola. Cuando desee una clave externa para un "lugar" generalizado, deberá usar claves externas genéricas, en su lugar, para poder elegir entre los diferentes tipos de lugares, y eso agrega mucha sobrecarga, si no es necesario.

Su mejor apuesta es usar la herencia normal: MTI. A continuación, puede crear una clave externa al Place y agregar cualquier elemento secundario de Place.

+0

de alguna manera, siempre me han gustado tus respuestas, esta no es una excepción. ¡¡Gracias!! – whatf

+0

¡Hah, yo también! De alguna manera, creo que Chris realmente sabe lo que está haciendo. –

+0

Guau, me gusta esta respuesta. Tengo una pregunta relacionada que quizás podría responder aquí http://stackoverflow.com/questions/32761441/convert-onetoonefield-to-multipletableinheritance si tiene tiempo? ¡Sería muy apreciado! – gabn88

0

Yo votaría por una clase abstracta si el dominio dicta que un place no puede existir si no es al menos uno de los otros.

Pero si un place no necesita tener nada, necesitaría herencia múltiple para acomodar los marcadores de posición (lotes vacantes)?

Imagino que los pros y los contras giran en torno a su afición a las tablas de bases de datos falsas. ¿Cómo implementa el ORM estas soluciones? Personalmente, no me gusta tener muchas tablas de campo individuales, pero mmm.

0

Yo votaría por la primera, porque es la más explícita. Y no veo ninguna ventaja de otros métodos.

1

Depende completamente del tipo de comportamiento que necesite.

¿Necesita realizar el mismo tipo de operaciones en lugares y restaurantes o áreas de juego? ¿Comprobará si sus servicios (restaurantes, etc.) están en el mismo lugar? ¿Es significativo tratar dos lugares con la misma dirección como diferentes y sus servicios asociados como diferentes?

Sin conocer las respuestas a este tipo de preguntas, es imposible decir cuál es la técnica más apropiada, ya que son técnicas muy diferentes, y no sustitutos generales entre sí.

El uso de herencia no debe ser dictado por una noción preconcebida sobre la taxonomía, porque no está allí para modelar taxonomía: es allí para proporcionar polimorfismo función (herencia miembro de datos es allí principalmente para facilitar que).

Cuestiones relacionadas