2008-12-15 17 views
28

He descompuesto los atributos comunes de dos clases en una clase base abstracta; sin embargo, tengo otro modelo que necesita hacer referencia a una de esas clases. No es posible hacer referencia a un ABC, ya que en realidad no tiene una tabla de base de datos.Configuración de una clave externa a una clase base abstracta con Django

El siguiente ejemplo debe ilustrar mi problema:

class Answer(models.Model): 
    ovramt = models.ForeignKey("Ovramt") 
    question = models.ForeignKey("Question") 
    answer = models.CharField(max_length=3, choices=(("yes","yes"),("no","no") ("NA","N/A")) 
    likelihood = models.IntegerField(choices=LIKELY_CHOICES) 
    consequence = models.IntegerField(choices=CONSEQUENCE_CHOICES) 

    class Meta: 
     abstract = True 

class Answer_A(Answer): 
    resident = models.ForeignKey("Resident") 
    def __unicode__(self): 
     return u"%s - %s - %s" %(self.ovramt.ssa.name, self.resident, self.question)  

class Answer_B(Answer): 
    def __unicode__(self): 
     return u"%s - %s" %(self.ovramt.ssa.name, self.question)  

class Answer_Risk(models.Model): 
    answer = models.ForeignKey("Answer") 
    risk = models.CharField(max_length=200) 

    def __unicode__(self): 
     return self.risk 

Answer_A y Answer_B son ligeramente diferentes en que Answer_A también necesita una relación FK a otra mesa. Answer_B también puede requerir algunos atributos específicos más adelante. El problema TODAVÍA existiría si tuviera Answer_B sea la superclase, y tenga Answer_A subclase o compórtala.

Un 'Riesgo' es el mismo ya sea Answer_A o Answer_B. También tengo otros modelos que necesitan hacer referencia a una "Respuesta" independientemente de su subtipo. ¿Cómo puede hacerse esto? ¿Cómo se puede hacer referencia a un tipo independientemente de su subtipo?

Actualización:
Estaba tratando de evitar una operación de unión, pero no creo que pueda hacerlo. ¿Valdría la pena tener la referencia a "Residente" en todas las "respuestas" y simplemente anularla cuando sea necesario? ¿O eso se considera una mala práctica?

Respuesta

18

A generic relation parece ser la solución. Pero complicará las cosas aún más.

Me parece a mí; la estructura de su modelo ya es más compleja de lo necesario. Simplemente fusionaría los tres modelos Answer en uno solo. De esta manera:

  • Answer_Risk funcionaría sin modificación.
  • Puede establecer resident en Ninguno (NULO) en el caso de Answer_A.
  • Puede devolver diferentes represantaciones de cadenas según resident == None. (en otras palabras, la misma funcionalidad)

Una cosa más; ¿Es probable que sus respuestas tengan más de un riesgo? Si van a tener ninguno o uno de los riesgos debe tener en cuenta después de implementaciones alternativas:

  • Usando un riesgo one-to-one relationship
  • degradar como un campo (o cualquier número de campos) en el interior Answer clase.

Mi principal preocupación es ni la estructura ni el rendimiento de base de datos (aunque estos cambios deberían mejorar el rendimiento), pero código de mantenimiento.

+0

Gracias por las sugerencias, pero las respuestas tendrán riesgos 1.M así como las soluciones 1..M, por lo que se requiere la tabla. Voy a ir con la configuración de residente a Ninguno cuando sea necesario, ya que parece ser la única diferencia entre los modelos. Si necesita cambiar más tarde lo haré entonces. –

+0

El enlace de relación genérica ya no es válido, para la última versión de desarrollo, vaya aquí: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#generic-relations –

+1

Gracias @HermanSchaaf, tengo actualizado el enlace. – muhuk

8

Mi instinto me sugiere sugerir la eliminación del modificador abstracto en la clase base. Obtendrá la misma estructura de modelo, pero la respuesta será su propia tabla. La desventaja de esto es que si estas son tablas grandes y/o sus consultas son complejas, las consultas en su contra podrían ser notablemente más lentas.

Como alternativa, puede mantener sus modelos como es, pero reemplaza el ForeignKey al animal con un GenericForeignKey. Lo que pierde en el azúcar sintáctico de la herencia del modelo, gana un poco en velocidad de consulta.

No creo que sea posible hacer referencia a un modelo base abstracto por ForeignKey (o cualquier cosa funcionalmente igual).

Cuestiones relacionadas