django-model-utilsをいろいろ試してみる その5 PassThroughManager
PassThroughManagerというものを試してみます。
まず普通のcustom managerを持つmodelを作成します。
from django.db import models import pytz from datetime import datetime class PostManager(models.Manager): def by_author(self, user): return self.filter(user=user) def published(self, **kwargs): return self.filter(published__lte=datetime.utcnow().replace(tzinfo=pytz.utc), **kwargs) class Post(models.Model): user = models.ForeignKey(User) title = models.CharField(max_length=100) published = models.DateTimeField() objects = PostManager() # objects = PassThroughManager.for_queryset_class(PostQuerySet)() def __unicode__(self): return self.title
適当にレコードを作成します。
>>> from apps.models import Post >>> from datetime import datetime, timedelta >>> import pytz >>> yesterday = datetime.utcnow().replace(tzinfo=pytz.utc) - timedelta(days=1) >>> tomorrow = datetime.utcnow().replace(tzinfo=pytz.utc) + timedelta(days=1) >>> u = User.objects.all()[0] >>> Post.objects.create(user=u, title='yesterday', published=yesterday) <Post: yesterday> >>> Post.objects.create(user=u, title='tomorrow', published=tomorrow) <Post: tomorrow>
custom managerにby_authorとis_publishedを定義してますが、これらはチェインできません。
>>> Post.objects.published() [<Post: yesterday>] >>> Post.objects.by_author(u) [<Post: yesterday>, <Post: tomorrow>] >>> Post.objects.by_author(u).published() Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'QuerySet' object has no attribute 'published'
そこでPassThroughManagerを使ってみます
from django.db import models from django.db.models.query import QuerySet import pytz from datetime import datetime from model_utils.managers import PassThroughManager class PostQuerySet(QuerySet): def by_author(self, user): return self.filter(user=user) def published(self, **kwargs): return self.filter(published__lte=datetime.utcnow().replace(tzinfo=pytz.utc), **kwargs) class Post(models.Model): user = models.ForeignKey(User) title = models.CharField(max_length=100) published = models.DateTimeField() # objects = PostManager() objects = PassThroughManager.for_queryset_class(PostQuerySet)() def __unicode__(self): return self.title
なんと、チェインできるようになります。
>>> Post.objects.published() [<Post: yesterday>] >>> u = User.objects.all()[0] >>> Post.objects.by_author(u) [<Post: yesterday>, <Post: tomorrow>] >>> Post.objects.by_author(u).published() [<Post: yesterday>]
これは使えそうな気がします。
関連 : django-model-utilsをいろいろ試してみる その1 StatusModel - brainstorm
関連 : django-model-utilsをいろいろ試してみる その2 TimeFramedModel - brainstorm
関連 : django-model-utilsをいろいろ試してみる その3 InheritanceManager - brainstorm
関連 : django-model-utilsをいろいろ試してみる その4 ModelTracker - brainstorm
参考 : carljm / django-model-utils / source / ― Bitbucket