通过 属性 或 Django Rest Framework 中的自定义字段订购模型
Order models by a property or custom field in Django Rest Framework
我有这种型号,我想通过 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
中按 属性 筛选
您不能按方法字段进行排序,因为排序是在数据库级别完成的,而数据库不知道该字段的存在。
但是你可以像这样使用 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
我有这种型号,我想通过 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
中按 属性 筛选您不能按方法字段进行排序,因为排序是在数据库级别完成的,而数据库不知道该字段的存在。
但是你可以像这样使用 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