Django分页(获取对象对应的页号)

发布于 2024-10-07 08:24:32 字数 1845 浏览 0 评论 0原文

我有一个分页,我正在尝试从对象页面获取索引页面(反向分页)

get_pagination_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_pagination_posts
从实例调用 Post 类是否正确?还有其他更好的方法可以做到这一点吗?
为什么我不能调用 super(Post, self).objects.get_pagination_posts 来执行相同的操作?
据我了解,由于对象无法访问其管理器,self.objects.get_pagination_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 

I have a paginate I am trying to get the index page from an object page (sort of pagination in reverse)

The get_paginated_posts returns a paginator for the model 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)
    .
    .

This is my model

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 

My concern is the Post.objects.get_paginated_posts call in the get_page function.
Is it right to call Post class from an instance? Is there any other better way to do this possible?
Why cannot I call super(Post, self).objects.get_paginated_posts to do the same?
I understand that self.objects.get_paginated_posts wont work because of absent access for the object to its manager.

Solved

Final code as suggested by 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 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

王权女流氓 2024-10-14 08:24:33

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

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

恕我直言,在 Post 方法中使用 PostManager 是可以的。不好的是,您将请求对象传递给它,而我认为您应该使用 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", "[email protected]")
    >>> 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

It's not the best idea what you're doing. Try to imagine how many queries it'll be translated to -- in the worst case you'd need to retrieve all user's posts from database!

I assume that you have some predefined ordering in your Post model (the one that Paginator uses). Use that to obtain the number of user's posts that precede that specific post record. If you divide that number by the POSTS_PER_PAGE value you'll get your page number.

IMHO using PostManager in Post methods is ok. What's not ok is that you're passing request object to it while I think you should use user_id for that (and permission checking should be really part of a view logic).

EDIT: example

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", "[email protected]")
    >>> 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文