2017-09-07 11 views
1

Django Rest views.pyにSQLクエリーを置く際に問題があります。Django Rest Framework-複雑なSQLクエリをviews.pyに配置する方法

views.py

from rest_framework import generics 
from ..models import Stat 
from .serializers import StatSerializer 

class StatListView(generics.ListAPIView): 
    queryset = Stat.objects.raw("SELECT parameter1, COUNT(*) FROM 
       statistic_stat GROUP BY parameter1 order by count(*) desc 
       LIMIT 10") 
    serializer_class = StatSerializer 

serializers.py

from rest_framework import serializers 
from ..models import Stat 

class StatSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Stat 
     fields = ('parameter1', 'parameter2') 

私はこのコードを実行すると、私のようなエラーが出る:「取得は、()つ以上の統計を返された - それは122を返しました! "

同じクエリが(同じデータベースに)別のスクリプトで動作し、このような結果を返します。

[('something1', 56), ('something2', 32), ('something3', 21), ('something4', 
19), ('something5', 10), ('something6', 8), ('something7', 4), ('something8', 
3), ('something9', 2), ('something10', 1)] 

トレースバック

Environment: 


Request Method: GET 
Request URL: http://127.0.0.1:8000/api/author/ 

Django Version: 1.11.3 
Python Version: 3.6.1 
Installed Applications: 
['django.contrib.admin', 
'django.contrib.auth', 
'django.contrib.contenttypes', 
'django.contrib.sessions', 
'django.contrib.messages', 
'django.contrib.staticfiles', 
'statistic', 
'rest_framework'] 
Installed Middleware: 
['django.middleware.security.SecurityMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 
'django.middleware.common.CommonMiddleware', 
'django.middleware.csrf.CsrfViewMiddleware', 
'django.contrib.auth.middleware.AuthenticationMiddleware', 
'django.contrib.messages.middleware.MessageMiddleware', 
'django.middleware.clickjacking.XFrameOptionsMiddleware'] 



Traceback: 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\django\core\handlers\exception.py" in inner 
    41.    response = get_response(request) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\django\core\handlers\base.py" in _get_response 
    187.     response = self.process_exception_by_middleware(e, request) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\django\core\handlers\base.py" in _get_response 
    185.     response = wrapped_callback(request, *callback_args, **callback_kwargs) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view 
    58.   return view_func(*args, **kwargs) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\django\views\generic\base.py" in view 
    68.    return self.dispatch(request, *args, **kwargs) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\views.py" in dispatch 
    489.    response = self.handle_exception(exc) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\views.py" in handle_exception 
    449.    self.raise_uncaught_exception(exc) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\views.py" in dispatch 
    486.    response = handler(request, *args, **kwargs) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\generics.py" in get 
    201.   return self.list(request, *args, **kwargs) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\mixins.py" in list 
    48.   return Response(serializer.data) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\serializers.py" in data 
    739.   ret = super(ListSerializer, self).data 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\serializers.py" in data 
    263.     self._data = self.to_representation(self.instance) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\serializers.py" in to_representation 
    657.    self.child.to_representation(item) for item in iterable 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\serializers.py" in <listcomp> 
    657.    self.child.to_representation(item) for item in iterable 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\serializers.py" in to_representation 
    488.     attribute = field.get_attribute(instance) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\fields.py" in get_attribute 
    445.    return get_attribute(instance, self.source_attrs) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\rest_framework\fields.py" in get_attribute 
    104.     instance = getattr(instance, attr) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\django\db\models\query_utils.py" in __get__ 
    116.     instance.refresh_from_db(fields=[self.field_name]) 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\django\db\models\base.py" in refresh_from_db 
    696.   db_instance = db_instance_qs.get() 

File "C:\Users\310041180\AppData\Local\Continuum\Miniconda3\lib\site-packages\django\db\models\query.py" in get 
    384.    (self.model._meta.object_name, num) 

Exception Type: MultipleObjectsReturned at /api/author/ 
Exception Value: get() returned more than one Stat -- it returned 877! 

任意のアイデアや提案は、何が間違っているの? ありがとうございました

+0

あなたは 'StatListView'をすべて投稿しましたか?より多くのコードがあるように見える –

+0

はい、それだけです。 "SELECT * FROM statistic_stat"のような単純なクエリで動作します。 – Neszwil

+0

トレースバックがなければ、推測になります。あなたはそれを提供してもらえますか? – Linovia

答えて

0

私はあなたが持っているエラーを再現することができないので、これが適切な答えであるかどうかわかりませんが、これは私のために働きます。

from rest_framework.generics import ListAPIView 
from rest_framework import serializers 

# you're not serializing a model and since you want to display that count I guess, I'd suggest changing the serializer to this. 
class StatSerializer(serializers.Serializer): 
    parameter1 = serializers.CharField(max_length=128, required=True) 
    count = serializers.integerField(required=True) 

    class Meta: 
     fields = ('parameter1', 'count') 

class StatListView(ListAPIView): 
    queryset = Stat.objects.raw("SELECT parameter1, COUNT(*) FROM 
       statistic_stat GROUP BY parameter1 order by count(*) desc 
       LIMIT 10") 
    serializer_class = StatSerializer 

    def list(self, request): 
     queryset = self.get_queryset() 
     # the serializer didn't take my RawQuerySet, so made it into a list 
     serializer = StatSerializer(list(queryset), many=True) 
     return Response(serializer.data) 
+0

serializers.pyファイルでこのコードを実行しようとしましたが、「名前ListAPIViewが定義されていません」というエラーが発生しました – Neszwil

+0

generics.ListAPIViewに変更しようとしましたが、シリアライザ 'StatSerializer'で' count'フィールドの値を取得しようとしたときのAttributeError シリアライザフィールドの名前が正しくない可能性があり、 'Stat'インスタンス。 元の例外テキストは 'Stat'オブジェクトに 'count'という属性がありません " – Neszwil

+0

定義されていない問題を修正するためのインポートが追加されました。 StatSerializer(serializers.Serializer)またはそれをクラスStatSerializer(serializers.ModelSerializer)に変更しましたか?ユースケースにはserializers.Serializerを使用する必要があります。 – Vincent

関連する問題