Настройка внешнего ключа для абстрактного базового класса с помощью Django

Я вынес общие атрибуты из двух классов в абстрактный базовый класс, однако у меня есть другая модель, которая должна ссылаться на любой из этих классов. Невозможно сослаться на ABC, поскольку на самом деле у него нет таблицы базы данных.

Следующий пример должен проиллюстрировать мою проблему:

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 и Answer_B немного отличаются тем, что Answer_A также требует отношения FK к другой таблице. Answer_B может также потребовать некоторые специфические атрибуты позже. Проблема все еще существовала бы, если бы у меня был Answer_B в качестве суперкласса - и имел бы подкласс Answer_A или составил бы его.

«Риск» один и тот же, будь то Ответ_A или Ответ_B. У меня также есть другие модели, которые должны ссылаться на «Ответ» независимо от его подтипа. Как это может быть сделано? Как вы можете ссылаться на тип независимо от его подтипа?

Обновление:
Я пытался избежать операции соединения, но не думаю, что смогу. Стоит ли иметь ссылку на «Резидент» во всех «Ответах» и просто обнулять ее там, где это необходимо? Или это считается очень плохой практикой?


person Josh Smeaton    schedule 15.12.2008    source источник


Ответы (2)


Решением может быть общая связь. Но это еще больше усложнит ситуацию.

Мне кажется; структура вашей модели уже сложнее, чем необходимо. Я бы просто слил все три Answer модели в одну. Сюда:

  • Answer_Risk будет работать без изменений.
  • Вы можете установить resident на None (NULL) в случае Answer_A.
  • Вы можете вернуть разные строковые репрезентации в зависимости от resident == None. (другими словами, такая же функциональность)

Еще кое-что; Ваши ответы связаны с более чем одним риском? Если у них не будет никакого риска или у них будет один риск, вам следует рассмотреть следующие альтернативные реализации:

Меня больше всего беспокоит не структура базы данных и не производительность (хотя эти изменения должны улучшить производительность), а удобство сопровождения кода.

person muhuk    schedule 15.12.2008

Мне кажется, что я предлагаю удалить модификатор abstract в базовом классе. Вы получите ту же структуру модели, но ответом будет собственная таблица. Обратной стороной этого является то, что если это большие таблицы и / или ваши запросы сложны, запросы к ним могут быть заметно медленнее.

В качестве альтернативы вы можете оставить свои модели как есть, но заменить ForeignKey to Answer на GenericForeignKey. То, что вы теряете в синтаксическом сахаре наследования модели, вы немного выигрываете в скорости выполнения запросов.

Я не верю, что можно ссылаться на абстрактную базовую модель с помощью ForeignKey (или чего-то такого же функционально).

person Daniel Naab    schedule 15.12.2008