2013-02-27 6 views
6

Używam Django Rest Framework Zauważyłem, że w części interfejsu API, którą można przeglądać w Internecie, znajduje się przycisk o nazwie "options" po kliknięciu pokazuje następujące ...Pokaż filtry i zamawianie w Django Rest Framework Requiem

HTTP 200 OK Vary: Accept Content-Type: text/html Allow: HEAD, GET, OPTIONS 
{ 
    "parses": [ 
     "application/json", 
     "application/x-www-form-urlencoded", 
     "multipart/form-data" 
    ], 
    "renders": [ 
     "application/json", 
     "text/html" 
    ], 
    "name": "Products", 
    "description": "API endpoint." 
} 

moje pytanie brzmi, czy mogę mimo to wymienić wszystkie opcje filtrowania i inne rzeczy w tym adresie URL?

Odpowiedz

6

Możesz zwrócić OPTIONS zwracając cokolwiek chcesz, przesuwając metodę .metadata() w widoku.

Zobacz tutaj: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/views.py#L340


Aktualizacja począwszy od 2015: Mamy teraz konfigurowalny metadanych API, które sprawia, że ​​łatwiej: http://www.django-rest-framework.org/api-guide/metadata/

+0

Czy możesz wyjaśnić lepiej, w jaki sposób można zastąpić .metadata() na widoku? to łącze wskazuje na "linię 340", ale nie wiem, do jakiej metody się odnosisz. – ePascoal

+1

Zobacz moją aktualizację powyżej. –

0

Można całkowicie to zrobić. Oto custom metadata class, który aktualizowałem tutaj na StackOverflow. To po prostu wyświetla listę wszystkich dostępnych filtrów, ich typów i ich wyborów. Zawiera też pola zamawiania, które są dostępne w klasie:

class SimpleMetadataWithFilters(SimpleMetadata): 

    def determine_metadata(self, request, view): 
     metadata = super(SimpleMetadataWithFilters, self).determine_metadata(request, view) 
     filters = OrderedDict() 
     if not hasattr(view, 'filter_class'): 
      # This is the API Root, which is not filtered. 
      return metadata 

     for filter_name, filter_type in view.filter_class.base_filters.items(): 
      filter_parts = filter_name.split('__') 
      filter_name = filter_parts[0] 
      attrs = OrderedDict() 

      # Type 
      attrs['type'] = filter_type.__class__.__name__ 

      # Lookup fields 
      if len(filter_parts) > 1: 
       # Has a lookup type (__gt, __lt, etc.) 
       lookup_type = filter_parts[1] 
       if filters.get(filter_name) is not None: 
        # We've done a filter with this name previously, just 
        # append the value. 
        attrs['lookup_types'] = filters[filter_name]['lookup_types'] 
        attrs['lookup_types'].append(lookup_type) 
       else: 
        attrs['lookup_types'] = [lookup_type] 
      else: 
       # Exact match or RelatedFilter 
       if isinstance(filter_type, RelatedFilter): 
        model_name = (filter_type.filterset.Meta.model. 
            _meta.verbose_name_plural.title()) 
        attrs['lookup_types'] = "See available filters for '%s'" % \ 
              model_name 
       else: 
        attrs['lookup_types'] = ['exact'] 

      # Do choices 
      choices = filter_type.extra.get('choices', False) 
      if choices: 
       attrs['choices'] = [ 
        { 
         'value': choice_value, 
         'display_name': force_text(choice_name, strings_only=True) 
        } 
        for choice_value, choice_name in choices 
       ] 

      # Wrap up. 
      filters[filter_name] = attrs 

     metadata['filters'] = filters 

     if hasattr(view, 'ordering_fields'): 
      metadata['ordering'] = view.ordering_fields 
     return metadata 

umieścić, że gdzieś w swoim projekcie, a następnie ustaw DEFAULT_METADATA_CLASS i powinno być wszystko gotowe, z nowym kluczem na swoim OPTIONS wniosków tak:

"filters": { 
    "sub_opinions": { 
     "type": "RelatedFilter" 
    }, 
    "source": { 
     "type": "MultipleChoiceFilter", 
     "choices": [ 
      { 
       "display_name": "court website", 
       "value": "C" 
      }, 
     ] 
    } 
    ...more... 
} 

to będzie również wyświetlać choices, odzwierciedlający sposób to obchodzić gdzie indziej w DRF.