Django-filter: Izinkan untuk mengganti pengambilan set kueri di FilterSet

Dibuat pada 21 Jun 2017  ·  4Komentar  ·  Sumber: carltongibson/django-filter

Judulnya mungkin sedikit membingungkan. Akan menyenangkan untuk memiliki metode filter generik yang dipanggil setiap kali queryset diambil dan pemfilteran untuk bidang diterapkan. Ya, saya dapat mengganti properti qs , pertama-tama dapatkan kumpulan kueri yang difilter dan kemudian terapkan prefetches. Tapi _tidak jelas apakah ini mungkin memiliki beberapa efek samping dan data yang diteruskan ke filter aman untuk diakses._

Ada kasus penggunaan saya.
Saya memfilter kumpulan kueri dengan hubungan M2M (seperti pada queryset.filter(items__field="foo") ). Namun saya ingin mendapatkan item yang diambil sebelumnya yang difilter oleh bidang itu juga.

Dengan kata lain filter saya terlihat seperti ini:

# 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 tunggal seperti ini berfungsi seperti yang diharapkan. Namun, saya mungkin memiliki beberapa filter filter_items_by_* + Saya perlu menerapkan pemfilteran yang sama untuk queryset dari prefetch untuk semua filter. Dan beberapa filter tidak menjadi masalah, karena mereka saling eksklusif dalam kasus saya. Tetapi filter + generik akan menyebabkan pengecualian.

Intinya adalah saya hanya dapat menerapkan satu prefetch untuk pencarian yang sama. Jadi, dalam kasus saya, saya hanya akan mendapatkan pengecualian.

Saya memiliki solusi sementara untuk masalah ini: semua filter_items_by_* melakukan pemfilteran wajib pada prefetch.
Dan di filter_queryset (setelah pemfilteran diterapkan), jika items tidak diambil sebelumnya (apa yang buruk karena saya memeriksa attrs yang dilindungi queryset), saya menerapkan prefetch dengan pemfilteran wajib. Tetapi harus ada cara yang lebih baik untuk menghadapi situasi seperti ini.

Saya harap contoh saya cukup jelas.

Komentar yang paling membantu

Hai @Alexx-G. Rilis 2.0 masih merupakan jalan keluar, tetapi akan ada beberapa perubahan pada API yang secara khusus menjawab pertanyaan ini. Pendeknya,

  • Anda ingin mengganti metode .filter_queryset() . Atribut .qs pada dasarnya akan bertanggung jawab untuk memanggil .filter_queryset() dan menyimpan hasilnya.
  • Anda bisa mendapatkan nilai filter untuk prefetching dari self.form.cleaned_data .

Semua 4 komentar

Hai @Alexx-G. Saya pikir ini bisa dimungkinkan dengan beberapa koordinasi antara filterset dan kelas filter yang relevan. Pada dasarnya, filter akan menambahkan sebuah Prefetch misalnya untuk nya parent filterset. FilterSet.qs kemudian hanya akan memanggil prefetch_related bila perlu.

Yang mengatakan, apa gunanya untuk ini? Saya berpendapat bahwa kemungkinan ada tempat yang lebih tepat untuk menangani prefetching.

Saya pikir ini bisa dimungkinkan dengan beberapa koordinasi antara filterset dan kelas filter yang relevan.

Saya telah memecahkan masalah saya dengan mengganti properti qs , tetapi sekali lagi, itu tidak jelas dan tidak didokumentasikan. Dengan kata lain, saya tidak yakin bahwa beberapa perubahan internal di kelas dasar tidak akan memengaruhi filterset saya (ok, saya telah menyematkan versi, tetapi bagaimanapun juga ..)

Yang mengatakan, apa gunanya untuk ini? Saya berpendapat bahwa kemungkinan ada tempat yang lebih tepat untuk menangani prefetching.

Saya percaya saya jelaskan di atas kasus penggunaan saya. Tidak masuk akal untuk memisahkan pemfilteran dan pengambilan awal, karena pengambilan awal bergantung pada filter. Dan jika saya memisahkannya, saya harus menduplikasi pemeriksaan yang sama untuk filter.

Dengan kata lain, jika ada deskripsi kontrak publik dari properti qs atau kait yang didokumentasikan untuknya, ini akan meningkatkan penyesuaian kumpulan filter.

Hai @Alexx-G. Rilis 2.0 masih merupakan jalan keluar, tetapi akan ada beberapa perubahan pada API yang secara khusus menjawab pertanyaan ini. Pendeknya,

  • Anda ingin mengganti metode .filter_queryset() . Atribut .qs pada dasarnya akan bertanggung jawab untuk memanggil .filter_queryset() dan menyimpan hasilnya.
  • Anda bisa mendapatkan nilai filter untuk prefetching dari self.form.cleaned_data .

Terima kasih banyak atas usaha Anda!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat