A criação de uma chave estrangeira para uma classe base abstrata com Django

votos
29

Eu fatoramos atributos comuns de duas classes em uma classe base abstrata, no entanto eu tenho um outro modelo que precisa referenciar qualquer uma dessas classes. Não é possível fazer referência a um ABC, uma vez que na verdade não tem uma tabela de banco de dados.

O exemplo a seguir deve ilustrar o meu 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 e Answer_B são ligeiramente diferentes no que Answer_A também precisa de um relacionamento FK para outra mesa. Answer_B também pode exigir alguns atributos específicos mais tarde. O problema seria ainda existem, se eu tivesse Answer_B ser a superclasse - e têm Answer_A subclasse ou compô-lo.

A 'Risk' é o mesmo se é Answer_A ou Answer_B. Eu também tenho outros modelos que precisam fazer referência a um 'Resposta', independentemente do que é sub-tipo. Como isso pode ser feito? Como você pode fazer referência a um tipo, independentemente do que é sub-tipo?

Update:
Eu estava tentando evitar uma operação participar, mas eu não acho que eu vou ser capaz. Seria vale a pena ter a referência a 'Resident' em all 'Resposta de e apenas anulando-lo quando necessário? Ou se que considerado uma prática muito ruim?

Publicado 15/12/2008 em 05:16
fonte usuário
Em outras línguas...                            


2 respostas

votos
18

A relação genérica parece ser a solução. Mas vai complicar ainda mais as coisas.

Parece para mim; sua estrutura de modelo já é mais complexo do que o necessário. Eu simplesmente fundir os três Answermodelos em um. Deste jeito:

  • Answer_Risk iria trabalhar sem modificação.
  • Você pode definir residentcomo Nenhum (NULL) em caso de uma Answer_A.
  • Você pode retornar diferentes represantations cordas dependendo resident == None. (por outras palavras, mesmo funcionalidade)

Mais uma coisa; são as suas respostas provável que tenha mais do que um risco? Se eles vão ter nenhum ou um risco que você deve considerar a seguinte implementações alternativas:

A minha principal preocupação é nem estrutura de banco de dados, nem performance (embora essas alterações devem melhorar o desempenho), mas manutenção de código .

Respondeu 15/12/2008 em 09:24
fonte usuário

votos
8

Meu instinto seria sugerir a remoção do modificador abstract na classe base. Você vai ter a mesma estrutura do modelo, mas Resposta será a sua própria mesa. A desvantagem desta situação é que, se estes são grandes tabelas e / ou suas consultas são complexas, consultas contra ele poderia ser visivelmente mais lento.

Alternativamente, você pode manter seus modelos como é, mas substitua o ForeignKey para animal com um GenericForeignKey . O que você perde no açúcar sintático de herança modelo, você ganha um pouco na velocidade de consulta.

Eu não acredito que é possível fazer referência a um modelo base abstrata por ForeignKey (ou qualquer coisa funcionalmente o mesmo).

Respondeu 15/12/2008 em 05:33
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more