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

Я выделил общие атрибуты из двух классов в абстрактный базовый класс, однако у меня есть другая модель, которая должна ссылаться на один из этих классов. Невозможно ссылаться на 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 или составлял бы его.

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

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

Ответы [ 2 ]

18 голосов
/ 15 декабря 2008

A родовое отношение , кажется, решение. Но это еще более усложнит ситуацию.

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

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

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

  • Использование отношения один к одному
  • Понижение риска как поля (или любого количества полей) внутри Answer класса.

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

8 голосов
/ 15 декабря 2008

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

Кроме того, вы можете оставить свои модели как есть, но заменить ForeignKey на Animal на GenericForeignKey . То, что вы теряете в синтаксическом сахаре наследования моделей, вы получаете немного в скорости запросов.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...