【问题标题】:Django Rest Framework create Queryset Group ByDjango Rest Framework 创建 Queryset Group By
【发布时间】:2019-05-20 22:44:03
【问题描述】:

你好我会写这行sql查询:

select rating, date, count(rating) as "Count" from analyse
where wkn='x' and date between 'x' and 'y' group by rating

我的模型类是这样的

class Analyse(models.Model):
date = models.DateField(blank=True, null=True)
week_day = models.CharField(blank=True, max_length=500)
location = models.CharField(blank=True, max_length=500)
old_rating = models.CharField(blank=True, max_length=500)
rating = models.CharField(blank=True, max_length=500)

序列化器和视图是这样的

class RatingSerializer(serializers.Serializer):
rating = serializers.ReadOnlyField()
total = serializers.ReadOnlyField()
date = serializers.DateField()#format='%Y'

class CompaniesChartsView(generics.ListAPIView):
http_method_names = ['get']
permission_classes = (AllowAny,)
serializer_class = RatingSerializer

def get(self, request, wkn, format=None):
    self.query = self.request.GET.get('chart')

    end = datetime.date.today()
    #start = datetime.date(datetime.date.today().year-1, 1, 1)
    start = datetime.date(datetime.date.today().year-1, 
    datetime.date.today().month, datetime.date.today().day)
    try:
        if self.query == "ratings":
            queryset = Analyse.objects.values('date', 'rating') 
                         .filter(
                         Q(wkn=wkn) &
                         Q(date__range=([start, end]))) 
                         .annotate(total=Count('rating'))

            serializer = RatingSerializer(queryset, many=True)

            print(serializer.data)
            print(connection.queries)
            return Response(serializer.data)
        else:
            return Response("Bad request", 
              status=status.HTTP_400_BAD_REQUEST)
    except:
        pass

Django 生成但是这个查询。这不是我想要的。

'SELECT "statistic_app_analyse"."date", 
 "statistic_app_analyse"."rating", 
 COUNT("statistic_app_analyse"."rating") AS "total" FROM 
 "statistic_app_analyse" WHERE ("statistic_app_analyse"."wkn" = 
  \'840400\' AND "statistic_app_analyse"."date" BETWEEN \'2017-12-20\' 
  AND \'2018-12-20\') GROUP BY "statistic_app_analyse"."date", 
  "statistic_app_analyse"."rating"'

Django 将日期字段添加到分组依据。

当我将查询更改为:

                      queryset = Analyse.objects.values('rating') 
                         .filter(
                         Q(wkn=wkn) &
                         Q(date__range=([start, end]))) 
                         .annotate(total=Count('rating'))

然后工作,但缺少日期。

当我将 Django 查询更改为行 sql 查询时

          queryset = Analyse.objects.raw("SELECT db.wkn, 
          db.rating, db.date, COUNT (*) as 'Count' FROM 
          analyse as db WHERE db.wkn='578580' and db.date like 
          '2018%'")

          queryset = list(queryset)

         serializer = RatingSerializer(queryset, many=True)
         return Response(serializer.data)

然后我得到一个错误

Internal Server Error: /api/companies/840400/charts/
Traceback (most recent call last):
File "/home/hendrik/PycharmProjects/automatic-information-extraction- 
from-stock-analysis/venv/lib/python3.5/site- 
packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/hendrik/PycharmProjects/automatic-information-extraction- 
from-stock-analysis/venv/lib/python3.5/site- 
packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/hendrik/PycharmProjects/automatic-information-extraction- 
from-stock-analysis/venv/lib/python3.5/site- 
packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, 
**callback_kwargs)
File "/home/hendrik/PycharmProjects/automatic-information-extraction- 
from-stock-analysis/venv/lib/python3.5/site- 
packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/hendrik/PycharmProjects/automatic-information-extraction- 
from-stock-analysis/venv/lib/python3.5/site- 
packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/hendrik/PycharmProjects/automatic-information-extraction- 
from-stock-analysis/venv/lib/python3.5/site- 
packages/rest_framework/views.py", line 497, in dispatch
self.response = self.finalize_response(request, response, *args, 
**kwargs)
File "/home/hendrik/PycharmProjects/automatic-information-extraction- 
from-stock-analysis/venv/lib/python3.5/site- 
packages/rest_framework/views.py", line 412, in finalize_response
 % type(response)
 AssertionError: Expected a `Response`, `HttpResponse` or 
 HttpStreamingResponse` to be returned from the view, but received a 
 <class 'NoneType'>`
 [20/Dec/2018 12:05:18] "GET /api/companies/840400/charts/? 
 chart=ratings 
 HTTP/1.1" 500 85144

感谢您的帮助

【问题讨论】:

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


    【解决方案1】:

    您的直接问题是视图从get() 返回None。这可以通过修改你的 try/except 来解决。

    def get(self, request, wkn, format=None):
        self.query = self.request.GET.get('chart')
    
        end = datetime.date.today()
        #start = datetime.date(datetime.date.today().year-1, 1, 1)
        start = datetime.date(datetime.date.today().year-1, 
        datetime.date.today().month, datetime.date.today().day)
        try:
            if self.query == "ratings":
                queryset = Analyse.objects.values('date', 'rating') 
                             .filter(
                             Q(wkn=wkn) &
                             Q(date__range=([start, end]))) 
                             .annotate(total=Count('rating'))
    
                serializer = RatingSerializer(queryset, many=True)
    
                print(serializer.data)
                print(connection.queries)
                return Response(serializer.data)
        except:
            pass
        return Response("Bad request", 
            status=status.HTTP_400_BAD_REQUEST)
    

    但是,捕获空白异常并传递它是一种糟糕的做法。如果你要传递一个异常,你应该知道可能会引发哪些异常,此时你应该捕获那些特定的异常,而不是简单地Exception。它的另一部分是它隐藏了你的代码出了什么问题。所以我建议你去:

    def get(self, request, wkn, format=None):
        self.query = self.request.GET.get('chart')
    
        end = datetime.date.today()
        #start = datetime.date(datetime.date.today().year-1, 1, 1)
        start = datetime.date(datetime.date.today().year-1, 
        datetime.date.today().month, datetime.date.today().day)
        if self.query == "ratings":
            queryset = Analyse.objects.values('date', 'rating') 
                         .filter(
                             Q(wkn=wkn) &
                             Q(date__range=([start, end]))) 
                         .annotate(total=Count('rating'))
    
            serializer = RatingSerializer(queryset, many=True)
    
            print(serializer.data)
            print(connection.queries)
            return Response(serializer.data)
        return Response("Bad request", 
            status=status.HTTP_400_BAD_REQUEST)
    

    为了获取日期以获取从GROUP BY 子句中删除的日期,请尝试将其从参数列表中删除到.values()

    queryset = Analyse.objects.values('rating') 
        .filter(
            Q(wkn=wkn) &
            Q(date__range=([start, end]))) 
        .annotate(total=Count('rating'))
    

    【讨论】:

    • 谢谢,但我什么时候将日期显示为额外字段?示例 {Date: xy, Rating: xy, total: 4} ...?
    • 对不起,我不明白。
    • 我的意思是如果我使用你的查询,那么正确的行 sql 查询就不会出现......我得到以下查询 [{'time': '0.003', 'sql': 'SELECT " statistic_app_analysis"."rating", COUNT("statistic_app_analysis"."rating") 作为 "total" 从 "statistic_app_analysis" WHERE ("statistic_app_analysis"."wkn" = \'840400\' AND "statistic_app_analysis"."date" BETWEEN \ '2017-12-21\' AND \'2018-12-21\') GROUP BY "statistic_app_analysis"."rating"'}] 但我会进行以下查询:select rating, date, count(rating) as "Count " 从分析 where wkn='x' and date between 'x' and 'y' group by rating
    • 不同的是我在选择栏中缺少了日期
    猜你喜欢
    • 1970-01-01
    • 2021-05-28
    • 2014-02-21
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    相关资源
    最近更新 更多