开发者

Django ForeignKey _set on an inherited model

I have two mo开发者_如何学Cdels Category and Entry. There is another model ExtEntry that inherits from 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)
    ...

I am able to use the Category.entry_set but I want to be able to do Category.blogentry_set but it is not available. If this is not available,then I need another method to get all ExtEntryrelated to one particular Category

EDIT My end goal is to have a QuerySet of ExtEntry objects

Thanks


I need another method to get all ExtEntryrelated to one particular Category

Easy:

ExtEntry.objects.filter(categories=my_category)

Do you know if there is a way to use the _set feature of an inherited

I don't know if there is a direct they for that. It is not mentioned in documentation.

But it is possible to get similar results with the 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

It is possible to select only entries which has ExtEntry:

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

Bad thing about the exclude is that it generates terrybly inefficient query:

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))

So my resume would be: use ExtEntry.objects.filter() to get your results. The backwards relations (object.something_set) is just a convenience and does not work in every situation.


See the documentation here for an explanation of how this works.

Basically, since you can get the parent model item, you should be able to get its child because an implicit one-to-one linkage is created.

The inheritance relationship introduces links between the child model and each of its parents (via an automatically-created OneToOneField).

So, you should be able to do:

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

It isn't documented that I can see, but I believe that generally, your one-to-one field name will be a lower class version of the inheriting model name.


The problem your running into is because Entry and ExtEntry are in separate tables. This may be the best solution for you, but you should be aware of that when you choose to use multi-table inheritance.

Something like category.entry_set.exclude(extentry=None) should work for you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜