Django分页(获取与该对象对应的页面编号)

时间:2010-12-13 13:38:28

标签: django django-models django-managers django-pagination

我有一个paginate我试图从对象页面获取索引页面(反向分页)

get_paginated_posts返回模型Post的分页器:

class PostManager(models.Manager):
    def get_paginated_posts(self, request=None):
        if request and request.user.has_perm('blog.change_post'):
            posts = super(PostManager, self).filter(is_update=False)
        else:        
            posts = super(PostManager, self).filter(publish=True, is_update=False)
        return Paginator(posts, POSTS_PER_PAGE)
    .
    .

这是我的模特

class Post(models.Model):
    .
    .
    .
    def get_page(self, request=None):
        paginator = Post.objects.get_paginated_posts(request)
        for i in range(1, paginator.num_pages+1):
            if self in paginator.page(i).object_list:                
                return i
            pass
        return False 

我关心的是get_page函数中的Post.objects.get_paginated_posts调用 从实例调用Post类是正确的吗?还有其他更好的方法吗?
为什么我不能致电super(Post, self).objects.get_paginated_posts来做同样的事情?
我理解self.objects.get_paginated_posts因为对象缺少对其经理的访问权限而无法工作。

解决

Tomasz Elendt建议的最终代码:

class PostManager(models.Manager):
    def get_paginated_posts(self, user=None):
        if user and user.has_perm('blog.change_post'):
            posts = super(PostManager, self).filter(is_update=False)
        else:        
            posts = super(PostManager, self).filter(publish=True, is_update=False)
        return Paginator(posts, POSTS_PER_PAGE)

class Post(models.Model):
    .
    def get_page(self, request=None):
        return self._default_manager.filter(is_update = False, time__gt=self.time).count()/POSTS_PER_PAGE +1 
        #Just a one line now :P 

1 个答案:

答案 0 :(得分:2)

这不是你最好的想法。试着想象它将被翻译成多少个查询 - 在最坏的情况下,你需要从数据库中检索所有用户的帖子!

我假设您的Post模型(Paginator使用的模型)中有一些预定义的排序。使用它来获取该特定帖子记录之前的用户帖子数。如果您将该数字除以POSTS_PER_PAGE值,您将获得您的页码。

PostManager方法中使用Post的恕我直言是可以的。什么是不正确的是你将请求对象传递给它,而我认为你应该使用user_id(并且权限检查应该是视图逻辑的一部分)。

编辑:示例

from django.db import models
from django.contrib.auth.models import User

POSTS_PER_PAGE = 10

class Post(models.Model):
    """
    >>> from datetime import datetime, timedelta
    >>> from django.db import connection
    >>> from django.conf import settings
    >>>
    >>> user = User.objects.create_user("test", "test@domain.com")
    >>> for i in xrange(100):
    ...     p = Post.objects.create(author=user,
    ...                             pub_date=datetime.now() - timedelta(hours=i))
    >>> post = Post.objects.all()[68]
    >>> settings.DEBUG = True    # monkey-patching settings - ugly
    >>> connection.queries = []  # cleaning previous queries
    >>> post.get_page()
    7
    >>> len(connection.queries)  # print number of queries of `get_page` call
    1
    """
    pub_date = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(User)
    class Meta:
        ordering = ["-pub_date"]

    def get_page(self):
        return self._default_manager.filter(author__id=self.author_id).filter(
            pub_date__gt=self.pub_date).count() / POSTS_PER_PAGE + 1