【问题标题】:Filter in django: the last post of each userdjango中的过滤器:每个用户的最后一篇文章
【发布时间】:2013-04-11 01:39:08
【问题描述】:

我有 2 个模型,作者和帖子,我如何制作一个过滤器,可以在一行中选择每个作者的最后一篇文章(按 id 字段)?,对我来说不好的方法是:

authors = Author.objects.all()
queryset = []
for author in authors:
    posts = Post.objects.filter(author=author).order_by('-id')
    if loc:
        queryset.append(posts[0])

具体来说,这是为了过滤我的 Tastypie 资源“PostResource”,这个过滤器只能给我每个用户的最后一篇文章,按创建排序

带有 okm 答案和美味派自定义过滤器的完整解决方案:

class LocationResource(ModelResource):
    user = fields.ForeignKey(AccountResource,'user' )
    class Meta:
        queryset = Location.objects.all().order_by('-id')
        resource_name = 'location'
        #excludes = ['id',]
        list_allowed_methods = ['post','get']
        authentication = ApiKeyAuthentication()
        authorization= Authorization()
        filtering = {'user': ALL_WITH_RELATIONS}

    def obj_create(self, bundle, **kwargs):
        if bundle.request.method == 'POST':
            return super(LocationResource, self).obj_create(bundle, user=bundle.request.user)

    def apply_authorization_limits(self, request, object_list):
        return object_list.filter(user=request.user)

    def dehydrate(self, bundle):
        return bundle

    def build_filters(self, filters=None):
        if filters is None: #if you don't pass any filters at all
            filters = {}

        orm_filters = super(LocationResource, self).build_filters(filters)

        if('only_lasts' in filters):

            query = filters['only_lasts']

            sqs = Location.objects.values('user_id').annotate(max_id=models.Max('id')).values('max_id')

            orm_filters["pk__in"] = sqs

        return orm_filters

【问题讨论】:

    标签: django django-models tastypie


    【解决方案1】:

    阅读the blog post,了解在 SQL 中按组获取顶行。

    如帖子中所述,您可以使用INJOIN

    IN为例:

    SELECT * FROM post_table 
    WHERE id IN (SELECT MAX(id) AS max_id FROM post_table GROUP BY author_id);
    

    SQL 可以写成 QuerySet 为:

    Post.objects.filter(pk__in=
        Post.objects.order_by().values('author_id').annotate(
            max_id=models.Max('id')).values('max_id'))
    

    SELECT MAX(id) AS max_id FROM post_table GROUP BY author_idQuerySet 模式是:

    Model.objects.order_by().values(...).annotate(foo=...).values('foo')
    ^------------^----------^-----------^-----------------^------------^
        \            \           \            \                \
    base queryset     \        GROUP BY        \           SELECT column
    or manager      remove possible           annotation part
                    useless ordering          Min/Max/...
    

    另外,您可以直接将 SQL 包装在 queryset.raw() 中。如果选择JOIN版本,.raw()方式更清晰。

    请注意,IN 子句可能在您的数据库后端存在性能问题,如果性能至关重要,您需要分析和调整索引。

    【讨论】:

    • 这篇文章已经很老了,但仍然很有帮助。谢谢。
    【解决方案2】:
    a = Author.objects.get(pk=1)
    #next line will give you the latest post of this particular author
    latest_post = a.post_set.latest('id')
    

    【讨论】:

    • 但我的问题是,如何在不迭代的情况下为所有作者制作这个(“在一次 ORM 调用中获取每个作者的最后一篇文章”,这意味着没有作者重复的文章列表)跨度>
    猜你喜欢
    • 2011-07-13
    • 1970-01-01
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多