This is an upgrade of snippet [1103](http://www.djangosnippets.org/snippets/1103/).
Exemplary usage:
class Blog(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=50)
blog = models.ForeignKey(Blog)
def __unicode__(self):
return self.title
class Meta:
abstract=True
class Article(Post):
text = models.TextField()
class Link(Post):
url = models.URLField()
blog = Blog(name="Exemplary blog")
blog.save()
Article(title="#1", text="Exemplary article 1", blog=blog).save()
Article(title="#2", text="Exemplary article 2", blog=blog).save()
Link(title="#3", url="http://exemplary.link.com/", blog=blog).save()
qs1 = Article.objects.all()
qs2 = Link.objects.all()
qsseq = QuerySetSequence(qs1, qs2)
# those all work also on IableSequence
len(qsseq)
len(QuerySetSequence(qs2, qs2))
qsseq[len(qs1)].title
# this is QuerySetSequence specific
qsseq.order_by('blog.name','-title')
excluded_homo = qsseq.exclude(title__contains="3")
# homogenic results - returns QuerySet
type(excluded_homo)
excluded_hetero = qsseq.exclude(title="#2")
# heterogenic results - returns QuerySetSequence
type(excluded_hetero)
excluded_hetero.exists()
You can implement more `QuerySet` API methods if needed. If full API is implemented it makes sense to also subclass the `QuerySet` class.
- queryset
- chain
- iterable
- indexable
This is the approach I've taken to access instances of child models from their parent. Functionally it's very similar to snippets [1031](http://www.djangosnippets.org/snippets/1031/) and [1034](http://www.djangosnippets.org/snippets/1034/), but without the use of `django.contrib.contenttypes`.
Usage:
class Post(ParentModel):
title = models.CharField(max_length=50)
objects = models.Manager()
children = ChildManager()
def __unicode__(self):
return self.title
def get_parent_model(self):
return Post
class Article(Post):
text = models.TextField()
class Photo(Post):
image = models.ImageField(upload_to='photos/')
class Link(Post):
url = models.URLField()
In this case, the `Post.children` manager will return a queryset containing instances of the appropriate child model, rather than instances of `Post`.
>>> Post.objects.all()
[<Post: Django>, <Post: Make a Tumblelog>, <Post: Self Portrait>]
>>> Post.children.all()
[<Link: Django>, <Article: Make a Tumblelog>, <Photo: Self Portrait>]
- model
- manager
- queryset
- inheritance
Django allows you to specify your own ModelManager with custom methods. However, these methods are chainable. That is, if you have a method on your PersonManager caled men(), you can't do this:
Person.objects.filter(birth_date__year=1978).men()
Normally, this isn't a problem, however your app may be written to take advantage of the chainability of querysets. For example, you may have an API method which may return a filtered queryset. You would want to call with_counts() on an already filtered queryset.
In order to overcome this, we want to override django's QuerySet class, and then make the Manager use this custom class.
The only downside is that your functions will not be implemented on the manager itself, so you'd have to call `Person.objects.all().men()` instead of `Person.objects.men()`. To get around this you must also implement the methods on the Manager, which in turn call the custom QuerySet method.