2014-10-23 2 views
2

Я работаю в проекте django, который мне нужно перечислить двумя разными моделями в одном представлении, упорядоченным по дате. Чтобы достичь этого, я использовал наследование, чтобы иметь возможность получить их в общий набор запросов. Мои модели:Как заставить запросы на суперклассу возвращать объекты подкласса? Или отклонить запрос запроса суперкласса к списку подкласса?

class Publication(models.model): 
    title = models.CharField(max_lengh = 200) 
    pub_date = models.DateTimeField(default = datetime.now) 
    headline = models.TextField() 

    class Meta: 
     abstract = True 

    @abc.abstractmethod 
    def say_hello(self): 
     return 

class New(Publication): 
    author = models.ForeignKey(Author) 
    source = models.CharField(max_length = 200) 
    categories = models.ManyToManyField(Category) 
    url = '/news/' 

    def say_hello(self): 
     return "Hello New!!!" 

class Opinion(Publication): 
    writer = models.ForeignKey(Writer) 
    style = .models.CharField(max_length=3, choices=(('txt', 'Text'), ('glr', 'Galery'))) 
    url = '/opinions/' 

    def say_hello(self): 
     return "Hello Opinion!!!" 

Я пытаюсь вызвать метод подкласса, а перебор в публикации QuerySet, как это:

publications = Publications.objects.all().order_by('-pub_date') 
for pub in publications: 
    pub.say_hello() 
    url = pub.url 

Проблема в том, что мой QuerySet возвращаются объектами издания, так что я могу 't доступ к дочерним атрибутам и методам, очевидно, что я имею дело с объектами Publication. Должен не быть Тот факт, что я установил публикацию как абстрактный класс, избегайте возможности иметь дело с объектами Publication ?. Не следует ли им не создавать экземпляр? Есть ли возможность выполнить класс QuerySet в классе Publication и вернуть список с дочерними объектами?

Если нет. Как вы, ребята, обходите эту ситуацию? Я мог бы использовать несколько советов.

ответ

1

Похоже, это может быть целесообразно использовать наследование нескольких таблиц и Джанго полиморфный:

Multi-таблица наследования: https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance

Джанго полиморфный: http://django-polymorphic.readthedocs.org/en/latest/

Multi-таблица наследования в Джанго позволяет иметь базовую модель/таблицу с вашими базовыми полями. Затем ваши подклассы определяют расширенные поля, которые помещаются в их собственные таблицы. Когда вы извлекаете записи с запросами из любого из подклассов, вы получите информацию для каждой записи как из базовой модели/таблицы, так и из подкласса model/table.

Чтобы получить записи с использованием набора запросов базовой модели и получить экземпляр соответствующего подкласса для каждого результата, один из вариантов - полиморфизм django. Я использовал его раньше, и он работает очень хорошо. У него определенно есть свои ограничения, но я бы дал ему шанс.

+0

Полиморфизм Django кажется отличным. Проблема в том, что у меня уже есть база данных. Я попытался выполнить южную миграцию, но polymorphic_ctype_id - NULL. Есть ли трюк для применения django-polymorphic в уже существующем населенном db? – Mauricio

+0

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

+0

Это сработало! Модуль django-polymorphic добавляет поле polymorphic_ctype к модели, которая ссылается на экземпляр из django.contrib.contenttypes.models импортирует ContentType. Я просто сделал это, потому что все мои дочерние модели добавили его объект contentType и сохранили его. – Mauricio

0

Каждый экземпляр публикации должен иметь либо атрибут «новый», либо атрибут «мнение», указывающий на один из двух подклассов соответственно. Имейте в виду, что каждый экземпляр имеет только один из этих атрибутов, поэтому, возможно, лучше попробовать ... кроме доступа к ним.

+0

Вы можете отредактировать исходный вопрос, указав дополнительную информацию, если хотите. –

0

Ну, я положу код для своего решения, который я получил благодаря ответу @David.

Как и было предложено Дэвидом, я использовал django-polymorphic, который велик и прост. Но тот факт, что у меня уже была заполненная база данных, усложнил ситуацию. Ничего сложного исправить.

Первое, что я сделал, это перенести базу данных с помощью south, чтобы добавить новое поле (polymorphic_ctype) в мою родительскую модель (в подклассы не добавлено ни одного поля).

Затем я использовал следующий код в режиме оболочки django на терминале. (python manage.py shell)

from jornal.models import Publication, New, Opinion 
from django.contrib.contenttypes.models import ContentType 

ctype_opinion = ContentType.objects.get(model = 'opinion', app_label = 'jornal') 
ctype_new = ContentType.objects.get(model = 'new', app_label = 'jornal') 
opinions = Opinion.objects.non_polymorphic().all() 
news = New.objects.non_polymorphic().all() 

for new in news: 
    new.polymorphic_ctype = ctype_new 
    new.save() 

for opinion in opinions: 
    opinion.polymorphic_ctype = ctype_opinion 
    opinion.save()