Django REST 프레임워크의 다양한 팁--5.수색하다

6054 단어 searchrestfuldjango
restframework에 검색 기능이 내장되어 있어 검색을 신속하게 실현할 수 있다
Django REST 프레임워크의 다양한 팁[디렉터리 인덱스]
위에 쓰다
모든 코드는 아래 두 버전에서 만들었어요.
django==1.8.8
djangorestframework==3.2.5 

조회
우리가 자주 조회를 해야 하는 것은 대체로 두 가지가 있는데 다음과 같다.
  • 다중 필드 모호 검색
  • 단일 필드 동일 검색
  • restframework가 Filter를 통해backends = (filters. Django Filter Backend, filters. Search Filter)로 이 일을 가볍게 끝냈다.
    문서
    해설하다
    DjangoFilterBackend 대응 Filterfields 속성, 같은 검색을 하려면 SearchFilter가 검색fields, 모호한 검색에 대응
    둘 다 Filter에서 사용할 수 있는 외키 사용속성으로 조회하기
    class CoursesView(ListCreateAPIView):
    
        filter_backends = (SchoolPermissionFilterBackend, filters.DjangoFilterBackend, filters.SearchFilter)
        permission_classes = (IsAuthenticated, ModulePermission)
        queryset = Course.objects.filter(is_active=True).order_by('-id')
        filter_fields = ('term',)
        search_fields = ('name', 'teacher', 'school__name')
        module_perms = ['course.course']
    
        def get_serializer_class(self):
            if self.request.method in SAFE_METHODS:
                return CourseFullMessageSerializer
            else:
                return CourseSerializer
    
        def get_queryset(self):
            return Course.objects.select_related('school', ).filter(
                    is_active=True, school__is_active=True, term__is_active=True).order_by('-id')

    메커니즘이 이렇습니다. 우선view 호출getqueryset에서queryset을 받아서 Filterbackends는 모든 backend를 가져와서 필터를 하기 때문에 일반적인 필터를 많이 쓸 수 있습니다django의queryset은list(list(qs)나get(qs[2])이나forin을 할 때만 진정한hit 데이터베이스이기 때문에 이 연결은 아무런 문제가 없습니다.
    class ListModelMixin(object):
        """
        List a queryset.
        """
        def list(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())
    
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
            
    class GenericAPIView(views.APIView):        
    
        def filter_queryset(self, queryset):
            """
            Given a queryset, filter it with whichever filter backend is in use.
    
            You are unlikely to want to override this method, although you may need
            to call it either from a list view, or from a custom `get_object`
            method if you want to apply the configured filtering backend to the
            default queryset.
            """
            for backend in list(self.filter_backends):
                queryset = backend().filter_queryset(self.request, queryset, self)
            return queryset

    Filter class 구현
    내가 정말 말하고 싶은 것은 Filter다. 왜냐하면 기본 Filterfield 관련 문서는 매우 상세하게 설명되어 있습니다. Filter class는 시도가 필요할 수도 있습니다.
    먼저 뷰를 보고 Filter를 사용하면class 때 Filter를 쓰지 마세요fields입니다. 대응하는 Class 중 메타 Class의 fields 속성이 Filter를 대체하기 때문입니다fields.
    class SchoolsView(ListCreateAPIView):
    
        permission_classes = (IsAuthenticated, ModulePermission)
        filter_backends = (filters.DjangoFilterBackend, filters.SearchFilter)
        filter_class = SchoolFilter
        search_fields = ('name', 'contact')
        module_perms = ['school.school']

    한 성, 시내의 모델을 보다
    class BaseLocation(TimeStampedModel):
        is_active = models.BooleanField(default=True, db_index=True)
    
        class Meta:
            abstract = True
    
        def __unicode__(self):
            return self.name
    
    
    class Province(BaseLocation):
        name = models.CharField(max_length=128, db_index=True)
    
    
    class City(BaseLocation):
        province = models.ForeignKey(Province)
        name = models.CharField(max_length=255, db_index=True)
    
    
    class District(BaseLocation):
        city = models.ForeignKey(City)
        name = models.CharField(max_length=255, db_index=True)

    school model
    class School(TimeStampedModel):
        MIDDLE_SCHOOL = 1
        COLLEGE = 2
        school_choices = (
            (MIDDLE_SCHOOL, u"  "),
            (COLLEGE, u"  ")
        )
        category = models.SmallIntegerField(
            choices=school_choices, db_index=True, default=MIDDLE_SCHOOL)
        name = models.CharField(max_length=255, db_index=True)
        city = models.ForeignKey(City)
        ...
        is_active = models.BooleanField(default=True, db_index=True)

    기본 Filter는 다음 Filter를 보십시오. 메타 클래스에 모델을 써야 하기 때문입니다.
    다음 두 줄을 설명하자면 등호 왼쪽의city는 메타의fields의city에 대응하고,name="city"는 Filter 메타class에서 대응하는 모델의속성,lookuptype은 대응하는 외키 속성을 가리킨다.사실 아래의 두 줄을 번역하면 모델이다.objects.filter (city name = fields에서city 변수가 전하는 값,city province name =fields에서province 변수가 전하는 값)
    city = django_filters.Filter(name="city", lookup_type='name')province = django_filters.Filter(name="city", lookup_type='province__name')
    # -*- coding: utf-8 -*-
    import django_filters
    
    class CityFilter(django_filters.FilterSet):
    
        city = django_filters.Filter(name="city", lookup_type='name')
        province = django_filters.Filter(name="city", lookup_type='province__name')
        # need to include Meta filed
        class Meta:
            fields = ['city', 'province']
    
    
    class DistrictFilter(django_filters.FilterSet):
    
        district = django_filters.Filter(name="district", lookup_type='name')
        city = django_filters.Filter(name="district", lookup_type='city__name')
        province = django_filters.Filter(name="district", lookup_type='city__province__name')
    
        # need to include Meta filed
        class Meta:
            fields = ['city', 'province', 'district']

    위 뷰에서 사용된 SchoolFilter
    class SchoolFilter(CityFilter):
    
        class Meta:
            model = School
            fields = ['category', 'city', 'province']

    주의
    검색 fileds는 like를 사용하여 만든 것이기 때문에 효율적인 문제가 존재합니다. 필요한 것이 있으면 다른 검색에 접속하십시오

    좋은 웹페이지 즐겨찾기