Поведение, которое вы хотели бы видеть, называется multi table inheritance. Каждый дочерний класс внутренне заканчивается тем же, что вы написали, поэтому с одним полем в базовый класс TitlePost
, но он внутренне управляется django.
Если вы множественное наследование как код ниже вы сможете написать:
k=TopTitlesPostPage.objects.create(hello="Hello",title_name="Heh")
Это означает, что поля будут непосредственно доступны.
from django.db import models
class TitlePost(models.Model):
title_name = models.CharField(max_length=100, unique=True)
title_body = models.TextField(max_length=30000)
title_why = models.TextField(max_length=250, null=True)
title_publication_date = models.DateTimeField('date')
likes = models.IntegerField(default=0)
dislikes = models.IntegerField(default=0)
def __unicode__(self):
return self.title_name
class TopTitlesPostPage(TitlePost):
hello = models.CharField(max_length=100, unique=True)
def __unicode__(self):
return self.hello
class NewTitlesPostPage(TitlePost):
hello = models.CharField(max_length=100, unique=True)
def __unicode__(self):
return self.hello
В случае, если вы никогда на самом деле будет ссылаться на базовый класс TitlePost
, но только его дети, возможно, было бы более целесообразным сделать `TitlePost abstract:
class TitlePost(models.Model):
title_name = models.CharField(max_length=100, unique=True)
title_body = models.TextField(max_length=30000)
title_why = models.TextField(max_length=250, null=True)
title_publication_date = models.DateTimeField('date')
likes = models.IntegerField(default=0)
dislikes = models.IntegerField(default=0)
class Meta:
abstract = True
def __unicode__(self):
return self.title_name
Создание TitlePost
аннотацию опускаем создание таблицы TitlePost
в базе данных, а дочерние модели получат поля базового класса, вставленные в их собственные таблицы отдельно. Если базовый класс предназначен только для факторизации общей функциональности, это предпочтительный путь.
Для огромных запросов это также будет иметь значение в производительности, поскольку ORM необходимо будет выполнить меньше JOIN
операций.
Невозможно установить внешние ключи для абстрактных моделей в Django. Однако вы можете установить внешние ключи для не абстрактного базового класса. Единственное ограничение заключается в том, что обратное отношение внешнего ключа вернет экземпляры базового класса. Вы можете обойти это ограничение, используя django-polymorphic.
Джанго Полиморфные позволяет запрашивать объекты базового класса, но получают экземпляры класса ребенка:
>>> Project.objects.create(topic="Department Party")
>>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner")
>>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
>>> Project.objects.all()
[ <Project: id 1, topic "Department Party">,
<ArtProject: id 2, topic "Painting with Tim", artist "T. Turner">,
<ResearchProject: id 3, topic "Swallow Aerodynamics", supervisor "Dr. Winter"> ]
Чтобы использовать Джанго полиморфные вам нужно только объявить свои модели с полиморфной моделью в качестве базового класса:
from django.db import models
from polymorphic import PolymorphicModel
class ModelA(PolymorphicModel):
field1 = models.CharField(max_length=10)
class ModelB(ModelA):
field2 = models.CharField(max_length=10)
class ModelC(ModelB):
field3 = models.CharField(max_length=10)
Внешние ключи также возвращают экземпляры дочерних классов, что действительно здорово, если вы пытаетесь быть полиморфными.
# The model holding the relation may be any kind of model, polymorphic or not
class RelatingModel(models.Model):
many2many = models.ManyToManyField('ModelA') # ManyToMany relation to a polymorphic model
>>> o=RelatingModel.objects.create()
>>> o.many2many.add(ModelA.objects.get(id=1))
>>> o.many2many.add(ModelB.objects.get(id=2))
>>> o.many2many.add(ModelC.objects.get(id=3))
>>> o.many2many.all()
[ <ModelA: id 1, field1 (CharField)>,
<ModelB: id 2, field1 (CharField), field2 (CharField)>,
<ModelC: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
Примите во внимание, что эти запросы будут slightly less performant.
Ничего себе, спасибо за всю информацию; это действительно помогает! Я определенно поиграю с этим методом! Поэтому, исходя из эффективности, я полагаю, что создание абстрактного класса для всех - лучший выбор, чем принятие полиморфного маршрута? Что бы вы выбрали между ними и почему? Если вы не возражаете ответить. – tear728
Когда дело доходит до производительности, никогда не оптимизируйте преждевременно. Как правило, вы только хотите принять это во внимание, когда у вас есть узкое место в базе данных. Полиморфный маршрут позволяет вам выполнять правильный полиморфизм, что означает программирование без утверждений и в полной мере использует утиную печать и обычно полезно, когда вы создаете приложения, которые должны быть расширяемы в будущем. Я бы использовал его для любого проекта, который больше, чем просто демо, но у него не будет десятков тысяч записей или сотен дополнительных моделей. –
Очень интересно. Я обязательно буду помнить об этом для будущих ссылок. Еще раз спасибо за информацию! – tear728