2013-08-02 13 views
6

Używam django-rest-framework z https://github.com/alex/django-filter/, ale pytanie dotyczy głównie filtru Django. Nie mogę zrozumieć, jak używać filtrów przy wyszukiwaniu "__in".Filtr Django '__in' lookup

Na przykład mam model:

class Book(models.Model): 
    name = models.CharField(max_length=100) 

class BookView(viewsets.ReadOnlyModelViewSet): 
    serializer_class = BookSerializer() 
    model = Book 
    filter_fields = ('id', 'name') 

i nie mogę używać url tak

/v1/książki/id__in = 1,2,3

?

, aby znaleźć książki o id 1, 2 lub 3

+0

Przeczytaj ten przewodnik: http://django-rest-framework.org/api-guide/filtering.html –

+1

ja już ją przeczytać . Rozumiem, że można ponownie zaimplementować metodę get_queryset i filtrować przez parametry request.GET, ale chcę najpierw spróbować użyć deklaratywnego podejścia django-filter. – user2645813

Odpowiedz

-1

Strona admin django tworzy tylko adresy URL pod szablonem app_name/model_na me/primary_key do edycji instancji modelu. Nie zapewnia filtrowania przez URLS.

Musisz utworzyć własny widok:

def myview(request): 
    # you can get parameters from request.GET or request.POST 
    selected_books = None 
    if request.method = "POST": 
     ids = request.POST["ids"].split("_") 
     selected_books = Book.objects.filter(id__in=ids) 

    return render_to_response('mytemplate.html', { 'selected_books': selected_books }, context_instance = RequestContext(request)) 

aw mytemplate.html:

{% for entry in selected_books %} 
    ... {{ entry }} ... 
{% endfor %} 

W urls.py dodać wpis do tego widoku.

Następnie spróbuj żądania GET do adresu URL z parametrami ?ids=1_2_3

+0

Dzięki, ale moje pytanie dotyczy aplikacji django-filter. – user2645813

3

Dokumentacja Django filtra jest rzadki. Możesz spróbować utworzyć niestandardowy filtr i określić typ wyszukiwania. Jest to dość zawiła:

class BookFilter(django_filters.FilterSet): 
    id = django_filters.NumberFilter(name="id", lookup_type="in") 

    class Meta: 
     model = Book 
     fields = ['id'] 

a następnie zmodyfikować swój pogląd użyć klasy filtra:

class BookView(viewsets.ReadOnlyModelViewSet): 
    serializer_class = BookSerializer() 
    model = Book 
    filter_fields = ('id', 'name') 
    filter_class = BookFilter 

Będziesz wtedy mógł do wyszukiwania książek poprzez ich identyfikatory (uwaga „__in” nie używany):

/v1/books/?id=1,2,3 
/v1/books/?id=1 
1

Dostosuj PKsField i PKsFilter do pola id (AutoField), a następnie będzie działać params zapytania: '/ v1/książki/id__in = 1,2,3'

from django.forms import Field 
 
from django_filters.filters import Filter 
 
from django.db.models import AutoField 
 

 

 
class PKsField(Field): 
 

 
    def clean(self, value): # convert '1,2,3' to {1, 2, 3} 
 
     return set(int(v) for v in value.split(',') if v.isnumeric()) if value else() 
 

 

 
class PKsFilter(Filter): 
 
    field_class = PKsField 
 

 

 
class BookFilter(FilterSet): 
 
    # ids = PKsFilter(name='id', lookup_type="in") # another way, query string: ?ids=1,2,3 
 

 
    filter_overrides = { 
 
     AutoField: { 
 
      'filter_class': PKsFilter, # override default NumberFilter by the PKsFilter 
 
      'extra': lambda f: { 
 
       'lookup_type': 'in', 
 
      } 
 
     } 
 
    } 
 

 
    class Meta: 
 
     model = Book 
 
     fields = { 
 
      'id': ('in',), 
 
     } 
 

 

 
from rest_framework import viewsets 
 

 

 
class BookView(viewsets.ModelViewSet): 
 
    queryset = ... 
 
    serializer_class = ... 
 
    filter_class = BookFilter

nadzieja, że ​​może pomóc. Dzięki.

5

Pytanie jest omówione w tym numerze: https://github.com/alex/django-filter/issues/137#issuecomment-77697870

Proponowane rozwiązanie byłoby utworzyć filtr niestandardowy sposób następujący:

from django_filters import Filter 
from django_filters.fields import Lookup 

from .models import Product 

class ListFilter(Filter): 
    def filter(self, qs, value): 
     value_list = value.split(u',') 
     return super(ListFilter, self).filter(qs, Lookup(value_list, 'in')) 

class ProductFilterSet(django_filters.FilterSet): 
    id = ListFilter(name='id') 

    class Meta: 
     model = Product 
     fields = ['id'] 

I Czy piszesz co następuje:

produkty /?id = 7,8,9

0

Zamiast /v1/books/?id__in=1,2,3 można użyć /v1/books/?id=1&id=2&id=3