2009-07-11 3 views
10

В принципе, у меня есть модель, где я создал суперкласс, который разделяют многие другие классы, а затем каждый из этих классов имеет некоторые уникальные функции, которые отличаются друг от друга. Скажем, класс A является суперклассом, а классы B, C и D являются дочерними элементами этого класса.Наследование наследования модели Django и внешние ключи

Как класс B, так и класс C могут иметь кратность класса D, однако я видел, что лучше всего установить отношение внешнего ключа в классе D, которое затем относится к его родительскому классу. Теперь на других языках я могу просто сказать, что у него есть отношение ForeignKey к классу A, а затем язык распознает истинный тип классов. Тем не менее, я не думаю, что это так, как это работает с Python.

Каков наилучший способ решения этой проблемы?

EDIT: Вот примерно то, что я имею в виду ...

class A(models.Model): 
    field = models.TextField() 

class B(A): 
    other = <class specific functionality> 

class C(A): 
    other2 = <different functionality> 

class D(A): 
    #I would like class D to have a foreign key to either B or C, but not both. 

По существу, класс B и класс C и имеют несколько классов двойка. Но конкретный класс D принадлежит только одному из них.

+0

Не могли бы вы объяснить, почему вам нужно наследование? – Evgeny

+0

Существует связанный с этим вопрос, есть некоторые хорошие ответы, которые могут помочь: https://stackoverflow.com/questions/1114767/django-model-inheritance-and-foreign-keys – Miranda

ответ

3

От Django Docs:

Например, если вы строили базы данных «мест», вы бы построить довольно стандартные вещи, такие как адрес, номер телефона и т.д. в базы данных. Затем, если вы хотите построить базы данных ресторанов на вершине мест, вместо того, чтобы повторять себя и тиражирование этих полей в модели ресторана, вы могли бы сделать Restaurant есть OneToOneField на место (потому что в ресторане «это« место, на самом деле, чтобы справиться с этим, вы, как правило, используете наследование, которое подразумевает неявное отношение один к одному ).

Обычно у вас есть Restaurant inherit from Place.К сожалению, вам нужно то, что я считаю хак: сделать ссылку один-к-одному из подкласса суперкласса (Restaurant к Place)

+0

Не задает ли django такую ​​ссылку один на один по умолчанию? например для унаследованных моделей с несколькими таблицами «restaurant.place» возвращает соответствующий экземпляр Place, без необходимости определять пользователем какие-либо отношения, отличные от наследования. –

+3

может быть, сейчас, но я не думаю, что это было в * 2009 *. – geowa4

+0

Вижу, спасибо! xxx –

1

Я вижу проблему здесь:

class D(A): 
    #D has foreign key to either B or C, but not both. 

не может это сделать. Вам придется добавить оба, потому что в SQL-столбцах необходимо точно определить.

Также, несмотря на то, что унаследованные модели, например, вы компилируете с syncdb - они, похоже, не ведут себя так, как вы ожидали бы - по крайней мере, я не мог заставить их работать. Я не могу объяснить, почему.

Это как FK работает в Django

class A(models.Model): 
    a = models.CharField(max_length=5) 

class B(models.Model): 
    a = model.ForeignKey(A, related_name='A') 
    b = models.CharField(max_length=5) 

class D(models.Model): 
    a = model.ForeignKey(A, related_name='A') 
    parent = model.ForeignKey(B, related_name='D') 

таким образом, вы можете эффективно иметь кратные D в B.

Наследование в моделях (например, класс B (A)) не работает Я бы ожидал этого. Может быть, кто-то еще может объяснить это лучше.

Взгляните на страницу this doc. Это касается отношений «много-к-одному» в джанго.

b = B() 
b.D_set.create(...) 
+0

Моя проблема: я хотел бы, чтобы класс D принадлежал либо класса А, либо класса В, а не обоих. Я уточню в своем вопросе. – AlbertoPL

2

Вы также можете сделать родовое отношение http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1 и проверки типов, чтобы ограничить его B или C при настройке или сохранении. Это, вероятно, больше работы, чем выяснение прямой ссылки, но может быть чище.

1

Один из способов сделать это, чтобы добавить промежуточный класс следующим образом:

class A(Model): 
    class Meta(Model.Meta): 
     abstract = True 
    # common definitions here 

class Target(A): 
    # this is the target for links from D - you then need to access the 
    # subclass through ".b" or ".c" 
    # (no fields here) 

class B(Target): 
    # additional fields here 

class C(Target): 
    # additional fields here   

class D(A): 
    b_or_c = ForeignKey(Target) 
    def resolve_target(self): 
     # this does the work for you in testing for whether it is linked 
     # to a b or c instance 
     try: 
      return self.b_or_c.b 
     except B.DoesNotExist: 
      return self.b_or_c.c 

Используя промежуточный класс (Target) гарантирует, что будет только одно звено из D либо B или C. Значит ли это, смысл? См. http://docs.djangoproject.com/en/1.2/topics/db/models/#model-inheritance для получения дополнительной информации.

В вашей базе данных будут таблицы для целей, B, C и D, но не A, поскольку это было отмечено как абстрактное (вместо этого столбцы, связанные с атрибутами на A, будут присутствовать в Target и D).

[Предупреждение: Я действительно не пробовал этот код - любые исправления приветствуются!]

+0

Очень хаки. Хотя это сработает. – clime

 Смежные вопросы

  • Нет связанных вопросов^_^