Настройка внешнего ключа для абстрактного базового класса с помощью 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 или составлял бы его.

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

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

15.12.2008 04:16:33
2 ОТВЕТА
РЕШЕНИЕ

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

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

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

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

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

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

18
6.01.2012 06:15:12
Спасибо за предложения, но ответы будут иметь риски 1..M, а также решения 1..M - поэтому таблица обязательна. Я собираюсь установить резидент в None, где это необходимо - так как это, кажется, единственное различие между моделями. Если это нужно изменить позже, я сделаю это тогда.
Josh Smeaton 15.12.2008 21:39:01
Ссылка общего отношения больше не действительна, для последней версии разработки, перейдите сюда: docs.djangoproject.com/en/dev/ref/contrib/contenttypes/…
Herman Schaaf 5.01.2012 09:30:17

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

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

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

8
21.08.2019 14:42:45