【问题标题】:Order models by a property or custom field in Django Rest Framework在 Django Rest Framework 中按属性或自定义字段对模型进行排序
【发布时间】:2026-01-24 17:45:01
【问题描述】:

我有这种型号,我想通过blog_views 属性订购,如何才能做到最好。

这是模型:

class Post(TimeStampedModel, models.Model):
    """Post model."""
    title = models.CharField(_('Title'), max_length=100, blank=False,
                             null=False)
    # TODO: Add image upload.
    image = models.ImageField(_('Image'), upload_to='blog_images', null=True,
                              max_length=900)
    body = models.TextField(_('Body'), blank=False)
    description = models.CharField(_('Description'), max_length=400,
                                   blank=True, null=True)
    slug = models.SlugField(default=uuid.uuid4(), unique=True, max_length=100)
    owner = models.ForeignKey(User, related_name='posts',
                              on_delete=models.CASCADE)
    bookmarks = models.ManyToManyField(User, related_name='bookmarks',
                                       default=None, blank=True)
    address_views = models.ManyToManyField(CustomIPAddress,
                                           related_name='address_views',
                                           default=None, blank=True)
    likes = models.ManyToManyField(User, related_name='likes', default=None,
                                   blank=True,
                                   )

    class Meta:
        ordering = ['-created']

    def __str__(self):
        """
        Returns a string representation of the blog post.
        """
        return f'{self.title} {self.owner}'

    @property
    def blog_views(self):
        """Get blog post views."""
        return self.address_views.all().count()

我阅读了有关annotate 的信息,但无法获得清晰的图像,我该如何制定这一点。

class PostList(generics.ListCreateAPIView):
    """Blog post lists"""
    queryset = Post.objects.all()
    serializer_class = serializers.PostSerializer
    authentication_classes = (JWTAuthentication,)
    permission_classes = (PostsProtectOrReadOnly, IsMentorOnly)
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['title', 'body',
                     'tags__name', 'owner__email',
                     'owner__username'
                     ]

我想按 URL 中的属性进行过滤

【问题讨论】:

    标签: python python-3.x django django-rest-framework


    【解决方案1】:

    您不能按方法字段排序,因为排序是在数据库级别完成的,而数据库不知道该字段存在。

    但是你可以像这样使用annotate

    from django.db.models import Count
    
    
    class PostList(generics.ListCreateAPIView):
        ...
        queryset = Post.objects.annotate(address_views_count=Count('address_views')).order_by('address_views_count')
    

    如果您希望订购是可选的,您可以使用filter_queryset:

    class PostList(generics.ListCreateAPIView):
        def filter_queryset(self, request, queryset, view):
            ordering = self.request.GET.get("ordering", None)
            if ordering == 'blog_views':
                queryset = queryset.annotate(address_views_count=Count('address_views')).order_by('address_views_count')
    
            return queryset
    

    【讨论】:

    • 那么,这个查询是在 url 级别完成的吗,这意味着例如我可以决定按如下视图排序:http://127.0.0.1:5000/api/v1/blogs/posts/?ordering=blog_views 或有另一个 url,如 http://127.0.0.1:5000/api/v1/blogs/posts/,无需排序,就像在 Django 中实现排序工作?
    • 已编辑.........
    • 好的,谢谢,但我收到了这个错误:Cannot resolve keyword 'blog_views' into field. Choices are: address_views, address_views_count, body, bookmarks, comments, created, description, id, image, likes, modified, owner, owner_id, slug, tags, title
    • Idk,我的答案不包含 blog_views 作为字段或变量。