2015-08-07 2 views
3

Как generics.RetrieveAPIView в Джанго рамка остальной должна возвращать только одну запись, я хотел бы использовать ограничение в методе запроса GET, как приведено нижекак использовать ограничение в рамках отдыха Джанго generics.RetrieveAPIView

class PortUserView(generics.RetrieveAPIView): 
    lookup_field = 'user' 

    def get_queryset(self): 

     return PortUser.objects.all()[:1] 

получения ошибка, подобная этой "Невозможно отфильтровать запрос после того, как срез был сделан".

Что не так с моим кодом?

+2

Я не понимаю, почему вы так поступаете. URL, связанный с вашим представлением, должен содержать параметр '', который является ключом для объекта, который требуется извлечь. Переопределить 'get_queryset' не нужно. Вы можете использовать [ModelViewSet] (http://www.django-rest-framework.org/api-guide/viewsets/#modelviewset) и [маршрутизатор] (http://www.django-rest-framework.org/ api-guide/routers /), которые будут генерировать URL-адреса для вас. – Xebax

+0

В url я не прохожу . См. Отредактированный фрагмент. – asitm9

ответ

5

Там нет необходимости для вас, чтобы беспокоиться о возвращении одного объекта из QuerySet во время retrieve. DRF будет обрабатывать это автоматически для вас, используя его .get_object(), определенный в GenericAPIView.

Вы можете использовать только приведенный ниже код, и DRF будет обрабатывать действие retrieve.

class PortUserView(generics.RetrieveAPIView): 
    lookup_field = 'user' 
    queryset = PortUser.objects.all() 

get_object (самость)

Возвращает экземпляр объекта, который должен использоваться для выносных. По умолчанию используется параметр lookup_field для фильтрации базы queryset.

Исходный код для retrieve действия:

def retrieve(self, request, *args, **kwargs): 
    instance = self.get_object() # here the object is retrieved 
    serializer = self.get_serializer(instance) 
    return Response(serializer.data) 

Мы можем видеть, что ФПИ использует функцию .get_object(), чтобы получить объект из QuerySet. Для выполнения фильтрации используется lookup_field, определенный в представлении.

Вот код get_object(), чтобы сделать более понятным.

def get_object(self): 
     """ 
     Returns the object the view is displaying. 

     You may want to override this if you need to provide non-standard 
     queryset lookups. Eg if objects are referenced using multiple 
     keyword arguments in the url conf. 
     """ 
     queryset = self.filter_queryset(self.get_queryset()) 

     # Perform the lookup filtering. 
     lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field 

     assert lookup_url_kwarg in self.kwargs, (
      'Expected view %s to be called with a URL keyword argument ' 
      'named "%s". Fix your URL conf, or set the `.lookup_field` ' 
      'attribute on the view correctly.' % 
      (self.__class__.__name__, lookup_url_kwarg) 
     ) 

     filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]} 
     obj = get_object_or_404(queryset, **filter_kwargs) # <-- can see that filtering is performed on the base of 'lookup_field' 

     # May raise a permission denied 
     self.check_object_permissions(self.request, obj) 

     return obj # will return the single retrieved object 
+0

Теперь я получаю ** «Исходный текст исключения был: Объект QuerySet не имеет атрибута« возраст ».. «**, хотя у меня есть "возраст" атрибут в PortUser модели после перекрывая определение функции извлечения (Self, запрос, * арг ** kwargs): экземпляра = self.get_object() # здесь объект извлекается сериалайзер = self.get_serializer (например, многие = True) обратный ответ (serializer.data) ' проблема была решена, но она возвращает список JSON. но я не хочу список Спасибо. – asitm9

+0

Можете ли вы опубликовать код, который вы пробовали. Кажется, что вы делали ' .age' где-то, что было бы неправильно.' Instance.age' был бы действителен, так как 'age' является n на 'PortUserModel'. В запросах 'list' будет возвращен список сериализованных объектов и в запросах' retrieve' будет возвращен сериализованный объект в виде словаря. –

1

Вам не нужно это делать. Вместо этого вы должны позволить рамки фильтровать QuerySet:

class PortUserView(generics.RetrieveAPIView): 
    queryset = PortUser.objects.all() 
+0

Да, это правильно, и 'lookup_field' должно быть добавлено, как в отредактированном фрагменте в вопросе. – Xebax

0

RetrieveAPIView по умолчанию возвращает один объект. Если возвращено несколько объектов, это приведет к возникновению исключения. Вам просто нужно определить запрос в вашем представлении.

class PortUserView(generics.RetrieveAPIView): 
    lookup_field = 'user' 
    queryset = PortUser.objects.all() 
    url_kwarg = 'whatever_field_you_want_to_map' 

Попробуйте карту в lookup_field к уникальному полю в модели, так что MultipleObjectsReturned исключение не поднимается внутри вида.

1
def get_object(self): 
    queryset = self.filter_queryset(self.get_queryset()) 
    lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field 

    assert lookup_url_kwarg in self.kwargs, (
     'Expected view %s to be called with a URL keyword argument ' 
     'named "%s". Fix your URL conf, or set the `.lookup_field` ' 
     'attribute on the view correctly.' % 
     (self.__class__.__name__, lookup_url_kwarg) 
    ) 
    filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]} 

    # ########################################################################################## 
    # obj = get_object_or_404(queryset, **filter_kwargs) 

    queryset = _get_queryset(queryset) 
    try: 
     return queryset.get(**filter_kwargs) 
    except AttributeError: 
     klass__name = queryset.__name__ if isinstance(queryset, type) else queryset.__class__.__name__ 
     raise ValueError(
      "First argument to get_object_or_404() must be a Model, Manager, " 
      "or QuerySet, not '%s'." % klass__name 
     ) 
    except queryset.model.DoesNotExist: 
     res = {"success": "false", "code": 404, "message": 'Product Not found'} 
     raise CustomValidation(res, 404) 
     # raise Http404('No %s matches the given query.' % queryset.model._meta.object_name) 

    # ########################################################################################## 
    # May raise a permission denied 

    self.check_object_permissions(self.request, obj) 
    return obj