Django ForeignKey _set по наследственной модели - PullRequest
7 голосов
/ 01 февраля 2011

У меня есть две модели Category и Entry.Есть другая модель ExtEntry, которая наследуется от Entry

class Category(models.Model):
    title = models.CharField('title', max_length=255)
    description = models.TextField('description', blank=True)
    ...

class Entry(models.Model):
    title = models.CharField('title', max_length=255)    
    categories = models.ManyToManyField(Category)
    ...

class ExtEntry(Entry):    
    groups= models.CharField('title', max_length=255)
    value= models.CharField('title', max_length=255)
    ...

Я могу использовать Category.entry_set, но я хочу иметь возможность Category.blogentry_set, но она недоступна.Если это недоступно, тогда мне нужен другой метод, чтобы получить все ExtEntry, относящиеся к одному конкретному Category

РЕДАКТИРОВАТЬ Моя конечная цель - иметь QuerySet of ExtEntry объектов

Спасибо

Ответы [ 3 ]

4 голосов
/ 01 февраля 2011

Мне нужен другой метод, чтобы получить все ExtEntryrelated для одной конкретной категории

Easy:

ExtEntry.objects.filter(categories=my_category)

Знаете ли вы, если есть способ использовать функцию _set унаследованного

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

Но с помощью select_related.

можно получить аналогичные результаты.
for e in category.entry_set.select_related('extentry'):
    e.extentry # already loaded because of `select_related`, 
               # however might be None if there is no Extentry for current e

Можно выбрать только те записи, которые имеют ExtEntry:

for e in category.entry_set.select_related('extentry').exlude(extentry=None):
    e.extentry # now this definitely is something, not None

Недостаток исключения состоит в том, что он генерирует ужасно неэффективный запрос:

SELECT entry.*, extentry.* FROM entry
LEFT OUTER JOIN `extentry` ON (entry.id = extentry.entry_ptr_id) 
WHERE NOT (entry.id IN (SELECT U0.id FROM entry U0 LEFT OUTER JOIN 
                        extentry U1 ON (U0.id = U1.entry_ptr_id) 
                        WHERE U1.entry_ptr_id IS NULL))

Таким образом, мое резюме будет: используйте ExtEntry.objects.filter(), чтобы получить ваши результаты. Отношения в обратном направлении (object.something_set) - это просто удобство и работает не во всех ситуациях.

2 голосов
/ 01 февраля 2011

См. Документацию здесь для объяснения того, как это работает.

По сути, поскольку вы можете получить элемент родительской модели, вы должны иметь возможность получить его дочерний элемент, поскольку создается неявная взаимно-однозначная связь.

Отношения наследования вводят связи между дочерней моделью и каждым из ее родителей (через автоматически созданный OneToOneField).

Итак, вы должны быть в состоянии сделать:

categories = Category.objects.all()
for c in categories:
    entries = c.entry_set.all()
    for e in entries:
        extentry = e.extentry
        print extentry.value

Не задокументировано, что я могу видеть, но я полагаю, что в общем случае ваше однозначное имя поля будет версия класса наследуемого имени модели.

0 голосов
/ 01 февраля 2011

Проблема, с которой вы столкнулись, заключается в том, что Entry и ExtEntry находятся в отдельных таблицах.Это может быть лучшим решением для вас, но вы должны знать об этом, когда решите использовать наследование нескольких таблиц.

Что-то вроде category.entry_set.exclude(extentry=None) должно работать для вас.

...