You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Django REST + Vue实现自定义排序功能的技术咨询

Django REST后端适配Vue前端排序功能实现方案

需求说明

前端通过sort_key(排序字段)和sort_type(排序类型:ascending/descending)传递排序参数,示例请求:

GET /api/v1/stocks/?sort_key=FBS&sort_type=ascending
GET /api/v1/stocks/?sort_key=FBS&sort_type=descending

现有代码问题分析

  1. Stock模型的Meta.ordering配置了"-present_fbs",但模型中不存在该字段,需改为"-fbs"避免报错。
  2. StocksApi的get_queryset固定了order_by("-fbs"),会忽略前端传递的排序参数,无法实现动态排序。

实现方案建议

方案一:自定义OrderingFilter(推荐,符合DRF规范)

通过继承DRF的OrderingFilter,适配前端传递的参数格式,同时实现字段映射与参数校验:

# views.py
from rest_framework.filters import OrderingFilter
from rest_framework.viewsets import GenericViewSet, ListModelMixin
from .models import Stock
from .serializers import StocksSerializer
from rest_framework.permissions import IsAuthenticated

class CustomSortFilter(OrderingFilter):
    def get_ordering(self, request, queryset, view):
        sort_key = request.query_params.get('sort_key')
        sort_type = request.query_params.get('sort_type')
        
        # 前端字段名 -> 模型字段名映射,可扩展其他字段
        field_mapping = {
            'FBS': 'fbs',
        }
        
        # 参数校验与排序逻辑
        if sort_key and sort_type:
            model_field = field_mapping.get(sort_key)
            if model_field and sort_type in ('ascending', 'descending'):
                return [f'-{model_field}'] if sort_type == 'descending' else [model_field]
        
        # 无合法参数时返回默认排序
        return ['-fbs']

class StocksApi(ListModelMixin, GenericViewSet):
    serializer_class = StocksSerializer
    permission_classes = (IsAuthenticated,)
    pagination_class = StocksDefaultPagination
    filter_backends = [CustomSortFilter]
    # 可选:明确允许排序的字段,增强安全性
    ordering_fields = ['fbs']

    def get_queryset(self):
        return Stock.objects.filter(store__user_id=self.request.user.pk)
# models.py
class Stock(models.Model):
    class Meta:
        verbose_name_plural = "Stocks"
        verbose_name = "Stock"
        ordering = ("-fbs",)  # 修正字段名,作为全局默认排序

    store = models.ForeignKey(Store, on_delete=models.CASCADE, null=True, verbose_name="Store")
    fbs = models.PositiveIntegerField(default=0, verbose_name="FBS")

方案二:手动在get_queryset中处理参数(简单场景适用)

直接在get_queryset方法中读取前端参数,动态调整查询集的排序:

# views.py
class StocksApi(ListModelMixin, GenericViewSet):
    serializer_class = StocksSerializer
    permission_classes = (IsAuthenticated,)
    pagination_class = StocksDefaultPagination

    def get_queryset(self):
        queryset = Stock.objects.filter(store__user_id=self.request.user.pk)
        sort_key = self.request.query_params.get('sort_key')
        sort_type = self.request.query_params.get('sort_type')
        
        field_mapping = {
            'FBS': 'fbs',
        }
        
        if sort_key and sort_type in ('ascending', 'descending'):
            model_field = field_mapping.get(sort_key)
            if model_field:
                order_str = f'-{model_field}' if sort_type == 'descending' else model_field
                return queryset.order_by(order_str)
        
        # 无合法参数时返回默认排序
        return queryset.order_by('-fbs')

关键注意事项

  • 字段映射:必须通过映射关系将前端字段名转换为模型字段名,避免直接使用用户输入的参数,防止非法字段排序或潜在安全问题。
  • 参数校验:需校验sort_type只能是ascending或descending,避免无效参数导致排序异常。
  • 默认排序:确保在未传递排序参数时,查询集有合理的默认排序逻辑,保持接口行为一致性。

内容的提问来源于stack exchange,提问作者Iren E

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:53:19