Django-filter: FilterSetμ—μ„œ 쿼리 μ„ΈνŠΈ 검색을 μž¬μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

에 λ§Œλ“  2017λ…„ 06μ›” 21일  Β·  4μ½”λ©˜νŠΈ  Β·  좜처: carltongibson/django-filter

제λͺ©μ΄ λ‹€μ†Œ μƒμ†Œν•  수 μžˆμŠ΅λ‹ˆλ‹€. 쿼리 μ„ΈνŠΈκ°€ κ²€μƒ‰λ˜κ³  ν•„λ“œμ— λŒ€ν•œ 필터링이 적용될 λ•Œλ§ˆλ‹€ ν˜ΈμΆœλ˜λŠ” 일반 filter λ©”μ„œλ“œκ°€ 있으면 쒋을 κ²ƒμž…λ‹ˆλ‹€. 예, qs 속성을 μž¬μ •μ˜ν•˜κ³  λ¨Όμ € ν•„ν„°λ§λœ 쿼리 μ„ΈνŠΈλ₯Ό κ°€μ Έμ˜¨ λ‹€μŒ ν”„λ¦¬νŽ˜μΉ˜λ₯Ό μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ _이것이 λΆ€μž‘μš©μ΄ μžˆμ„ 수 있고 필터에 μ „λ‹¬λœ 데이터가 μ•‘μ„ΈμŠ€ν•˜κΈ°μ— μ•ˆμ „ν•œμ§€ μ—¬λΆ€λŠ” ν™•μ‹€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€._

제 μ‚¬μš© 사둀가 μžˆμŠ΅λ‹ˆλ‹€.
queryset.filter(items__field="foo") μ—μ„œμ™€ 같이 M2M κ΄€κ³„λ‘œ 쿼리 μ„ΈνŠΈλ₯Ό ν•„ν„°λ§ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ ν•΄λ‹Ή ν•„λ“œλ‘œ ν•„ν„°λ§λœ 미리 κ°€μ Έμ˜¨ ν•­λͺ©λ„ κ°€μ Έμ˜€κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

즉, λ‚΄ ν•„ν„°λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

# In my filterset
def filter_items_by_field(self, queryset, name, value):
        queryset = queryset.all().filter(
            items__field=value,
        )
        prefetched_items = Prefetch(
            'items',
            Item.objects..filter(
                field=value,
            ),
        )
        return queryset.prefetch_related(prefetched_items)

# In my vieset
def get_queryset(self):
        queryset = super().get_queryset()
        # This should be applied everytime
        prefetched_items = Prefetch(
            'items',
            Item.objects..filter(
                another_field=some_value,
            ),
        )
        return queryset.prefetch_related(prefetched_items)

이와 같은 단일 ν•„ν„°λŠ” μ˜ˆμƒλŒ€λ‘œ μž‘λ™ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ filter_items_by_* ν•„ν„°κ°€ μ—¬λŸ¬ 개 μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. + λͺ¨λ“  필터에 λŒ€ν•΄ ν”„λ¦¬νŽ˜μΉ˜μ—μ„œ 쿼리 μ„ΈνŠΈμ— λŒ€ν•΄ λ™μΌν•œ 필터링을 μ μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. 그리고 μ—¬λŸ¬ ν•„ν„°λŠ” λ¬Έμ œκ°€ λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 제 κ²½μš°μ—λŠ” μƒν˜Έ 배타적이기 λ•Œλ¬Έμž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ ν•„ν„° + μΌλ°˜μ€ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.

μš”μ μ€ λ™μΌν•œ μ‘°νšŒμ— λŒ€ν•΄ ν•˜λ‚˜μ˜ ν”„λ¦¬νŽ˜μΉ˜λ₯Ό μ μš©ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ”°λΌμ„œ 제 κ²½μš°μ—λŠ” μ˜ˆμ™Έκ°€ λ°œμƒν•©λ‹ˆλ‹€.

이 λ¬Έμ œμ— λŒ€ν•œ μž„μ‹œ ν•΄κ²° 방법이 μžˆμŠ΅λ‹ˆλ‹€. λͺ¨λ“  filter_items_by_* λŠ” ν”„λ¦¬νŽ˜μΉ˜μ—μ„œ ν•„μˆ˜ 필터링을 μˆ˜ν–‰ν•©λ‹ˆλ‹€.
그리고 filter_queryset (필터링이 적용된 ν›„) items κ°€ ν”„λ¦¬νŽ˜μΉ˜λ˜μ§€ μ•ŠμœΌλ©΄(쿼리셋 보호 속성을 κ²€μ‚¬ν•˜κΈ° λ•Œλ¬Έμ— λ‚˜μœ 점) ν•„μˆ˜ 필터링과 ν•¨κ»˜ ν”„λ¦¬νŽ˜μΉ˜λ₯Ό μ μš©ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이와 같은 상황에 λŒ€μ²˜ν•˜λŠ” 더 λ‚˜μ€ 방법이 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

λ‚΄ μ˜ˆκ°€ μΆ©λΆ„νžˆ λͺ…ν™•ν•˜κΈ°λ₯Ό λ°”λžλ‹ˆλ‹€.

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

μ•ˆλ…•ν•˜μ„Έμš” @Alexx-Gμž…λ‹ˆλ‹€. 2.0 λ¦΄λ¦¬μŠ€λŠ” 아직 ν•΄κ²° 방법이 μ—†μ§€λ§Œ 이 μ§ˆλ¬Έμ„ ꡬ체적으둜 ν•΄κ²°ν•˜κΈ° μœ„ν•΄ API에 λͺ‡ 가지 λ³€κ²½ 사항이 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. μš”μ»¨λŒ€,

  • .filter_queryset() λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ν•˜κ³  싢을 κ²ƒμž…λ‹ˆλ‹€. .qs 속성은 기본적으둜 .filter_queryset() 호좜 및 κ²°κ³Ό 캐싱을 λ‹΄λ‹Ήν•©λ‹ˆλ‹€.
  • self.form.cleaned_data μ—μ„œ ν”„λ¦¬νŽ˜μΉ˜μš© ν•„ν„° 값을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

λͺ¨λ“  4 λŒ“κΈ€

μ•ˆλ…•ν•˜μ„Έμš” @Alexx-Gμž…λ‹ˆλ‹€. ν•„ν„° μ„ΈνŠΈμ™€ κ΄€λ ¨ ν•„ν„° 클래슀 κ°„μ˜ μ‘°μ •μœΌλ‘œ 이것이 κ°€λŠ₯ν•  수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. 기본적으둜 ν•„ν„°λŠ” Prefetch μΈμŠ€ν„΄μŠ€λ₯Ό parent ν•„ν„° μ„ΈνŠΈμ— μΆ”κ°€ν•©λ‹ˆλ‹€. FilterSet.qs λŠ” μ μ ˆν•œ 경우 prefetch_related λ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

즉, μ΄κ²ƒμ˜ μ‚¬μš© μ‚¬λ‘€λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ? ν”„λ¦¬νŽ˜μΉ­μ„ μ²˜λ¦¬ν•˜κΈ°μ— 더 μ μ ˆν•œ μž₯μ†Œκ°€ μžˆλ‹€κ³  μ£Όμž₯ν•©λ‹ˆλ‹€.

ν•„ν„° μ„ΈνŠΈμ™€ κ΄€λ ¨ ν•„ν„° 클래슀 κ°„μ˜ μ‘°μ •μœΌλ‘œ 이것이 κ°€λŠ₯ν•  수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

qs 속성을 μž¬μ •μ˜ν•˜μ—¬ 이미 λ‚΄ 문제λ₯Ό ν•΄κ²°ν–ˆμ§€λ§Œ λ‹€μ‹œ λͺ…ν™•ν•˜μ§€ μ•Šκ³  λ¬Έμ„œν™”λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. 즉, κΈ°λ³Έ 클래슀의 일뢀 λ‚΄λΆ€ λ³€κ²½ 사항이 λ‚΄ ν•„ν„° μ„ΈνŠΈμ— 영ν–₯을 λ―ΈμΉ˜μ§€ μ•Šμ„ 것이라고 ν™•μ‹ ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

즉, μ΄κ²ƒμ˜ μ‚¬μš© μ‚¬λ‘€λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ? ν”„λ¦¬νŽ˜μΉ­μ„ μ²˜λ¦¬ν•˜κΈ°μ— 더 μ μ ˆν•œ μž₯μ†Œκ°€ μžˆλ‹€κ³  μ£Όμž₯ν•©λ‹ˆλ‹€.

λ‚˜λŠ” μœ„μ—μ„œ λ‚΄ μ‚¬μš© 사둀λ₯Ό μ„€λͺ…ν–ˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. ν”„λ¦¬νŽ˜μΉ˜λŠ” 필터에 μ˜μ‘΄ν•˜κΈ° λ•Œλ¬Έμ— 필터링과 ν”„λ¦¬νŽ˜μΉ­μ„ λΆ„λ¦¬ν•˜λŠ” 것은 μ˜λ―Έκ°€ μ—†μŠ΅λ‹ˆλ‹€. 그리고 그것듀을 λΆ„λ¦¬ν•˜λ©΄ 필터에 λŒ€ν•΄ λ™μΌν•œ 검사λ₯Ό λ³΅μ œν•΄μ•Ό ν•©λ‹ˆλ‹€.

즉, qs μ†μ„±μ˜ 곡개 계약에 λŒ€ν•œ μ„€λͺ…μ΄λ‚˜ 이에 λŒ€ν•œ λ¬Έμ„œν™”λœ 후크가 μžˆλŠ” 경우 ν•„ν„° μ„ΈνŠΈμ˜ μ‚¬μš©μž μ •μ˜κ°€ ν–₯μƒλ©λ‹ˆλ‹€.

μ•ˆλ…•ν•˜μ„Έμš” @Alexx-Gμž…λ‹ˆλ‹€. 2.0 λ¦΄λ¦¬μŠ€λŠ” 아직 ν•΄κ²° 방법이 μ—†μ§€λ§Œ 이 μ§ˆλ¬Έμ„ ꡬ체적으둜 ν•΄κ²°ν•˜κΈ° μœ„ν•΄ API에 λͺ‡ 가지 λ³€κ²½ 사항이 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. μš”μ»¨λŒ€,

  • .filter_queryset() λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ν•˜κ³  싢을 κ²ƒμž…λ‹ˆλ‹€. .qs 속성은 기본적으둜 .filter_queryset() 호좜 및 κ²°κ³Ό 캐싱을 λ‹΄λ‹Ήν•©λ‹ˆλ‹€.
  • self.form.cleaned_data μ—μ„œ ν”„λ¦¬νŽ˜μΉ˜μš© ν•„ν„° 값을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

λ…Έλ ₯ν•΄ μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€!

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰