Наследование модели Django с использованием одной таблицы БД - проблемы с доступом к подклассу из суперкласса - PullRequest
1 голос
/ 20 июля 2011

Я разрабатываю приложение Django, используя Oracle, без изменений в схеме БД.У меня есть одна таблица, в которой существуют все Thesis, которые можно разделить на два непересекающихся набора: PhdThesis и BscMscThesis.У меня также есть модель Review, которая ссылается на таблицу Thesis DB и не заботится о том, является ли она PhdThesis или BscMscThesis, поэтому я хотел бы сохранить Thesis как abstract = False class.

class Thesis(models.Model):
    # Primary key  has to be specified explicite here for inheritance to work?
    id = models.DecimalField(db_column="ID", max_digits=10, decimal_places=0, primary_key=True)
    class Meta:
        db_table = "DZ_PRACE_CERT"
        managed = False

class Person(models.Model):
    class Meta:
        db_table = "MV_OSOBY"
        managed = False


class BscMscThesisManager(models.Manager):
    def get_query_set(self):
        return super(BscMscThesisManager, self).get_query_set().filter(personbscmscdiploma__isnull=False)

class BscMscThesis(Thesis):
    # needed for inheritance?
    thesis = models.OneToOneField(Thesis, db_column="ID", primary_key=True, parent_link=True)
    authors = models.ManyToManyField(Person, through="PersonBscMscDiploma", related_name='author_of_bsc_msc_theses')
    objects = BscMscThesisManager()

    class Meta:
        db_table = "DZ_PRACE_CERT"
        managed = False

class PersonBscMscDiploma(models.Model):
    bsc_msc_thesis = models.ForeignKey(BscMscThesis, db_column="PRC_CERT_ID")


class PhdThesisManager(models.Manager):
    def get_query_set(self):
        return super(PhdThesisManager, self).get_query_set().filter(personphddiploma__isnull=False)

class PhdThesis(Thesis):
    # needed for inheritance?
    thesis = models.OneToOneField(Thesis, db_column="ID", primary_key=True, parent_link=True)
    authors = models.ManyToManyField(Person, through="PersonPhdDiploma", related_name='author_of_phd_theses')
    objects = PhdThesisManager()

    class Meta:
        db_table = "DZ_PRACE_CERT"
        managed = False

class PersonPhdDiploma(models.Model):
    phd_thesis = models.ForeignKey(PhdThesis, db_column="PRC_CERT_ID")

Проблема, с которой я столкнулся:

>>> Thesis.objects.all()[0].phdthesis
<PhdThesis: Uniwersytecki System Obsługi Studiów. Parametryzowane filtry>
>>> Thesis.objects.all()[0].bscmscthesis
<BscMscThesis: Uniwersytecki System Obsługi Studiów. Parametryzowane filtry>
>>> Thesis.objects.all()[0].phdthesis.authors.all()
[]
>>> Thesis.objects.all()[0].bscmscthesis.authors.all()
[<Person: Jan1912 Kowalski1912>]
>>> Thesis.objects.all()[0].id
Decimal('903')
>>> BscMscThesis.objects.get(id=903)
<BscMscThesis: Uniwersytecki System Obsługi Studiów. Parametryzowane filtry>
>>> PhdThesis.objects.get(id=903)
DoesNotExist: PhdThesis matching query does not exist.

PhdThesis.objects.all() и BscMscThesis.objects.all() возвращает два непересекающихся набора, как и предполагалось.

Почему Thesis.objects.all()[0].phdthesis не возвращает None илиNotExist в приведенном выше примере?Что я могу сделать, чтобы получить такое поведение?

1 Ответ

1 голос
/ 10 августа 2011

Кажется, у Джанго нет простого способа сделать это. В итоге я реализовал такие методы, как is_phd() и is_bsc_msc(), и использовал их следующим образом:

def get_absolute_url(self):
    if self.is_phd():
        return self.phdthesis.get_absolute_url()
    else:
        return self.bscmscthesis.get_absolute_url()
...