Saya memiliki tampilan, AccountList
, yang mencoba membuat tabel Django_table2. Kode sumber tampilan:
class AccountList(SingleTableMixin, FilterView):
model = Account
table_class = AccountTable
template_name = 'accounts/account_list.html'
context_table_name = 'object_list'
ordering = ['vps']
filterset_class = AccountFilter
Tampilan ini sedang menggunakan filterset ini (dari Django_filters):
import django_filters
from accounts.models import Account
class AccountFilter(django_filters.FilterSet):
class Meta:
model = Account
fields = ['is_suspended', 'is_abandoned']
is_suspended = django_filters.BooleanFilter(name='is_suspended', initial='False')
is_abandoned = django_filters.BooleanFilter(name='is_abandoned', initial='False')
def __init__(self, data=None, *args, **kwargs):
# if filterset is bound, use initial values as defaults
if data is not None:
# get a mutable copy of the QueryDict
data = data.copy()
for name, f in self.base_filters.items():
initial = f.extra.get('initial')
# filter param is either missing or empty, use initial as default
if not data.get(name) and initial:
data[name] = initial
super().__init__(data, *args, **kwargs)
Menggunakan templat ini:
{% if filter %}
<form action="" method="get" class="form form-inline">
{{ filter.form.as_p }}
<input type="submit" />
</form>
{% endif %}
{% render_table object_list %}
{% endblock %}
Ini saya dari urls.py saya
path('', login_required(AccountList.as_view())),
Ketika saya mengunjungi halaman saya, 127.0.0.1:8000
, saya melihat bahwa filter tidak disetel:
Tetapi kemudian jika saya melakukannya 127.0.0.1:8000?page=1
, saya melihat filter diinisialisasi dengan benar:
Coba gunakan nilai boolean False
aktual alih-alih nilai string 'False'
.
Jadi ketika saya mencoba yang berikut ini:
is_suspended = django_filters.BooleanFilter(name='is_suspended', initial=False)
is_abandoned = django_filters.BooleanFilter(name='is_abandoned', initial=False)
Beginilah cara filter dirender pada 127.0.0.1:8000/
Meskipun filter diberikan dengan nilai yang tepat, filter tidak berpengaruh karena saya masih dapat melihat akun yang ditangguhkan atau ditinggalkan.
Selain itu, ketika saya mengunjungi halaman 2 dengan menekan tombol 2
di bagian bawah, saya mendapatkan http://127.0.0.1:8000/?page=2
dengan filter diatur ulang ke Unknown
.
Apakah Anda melihat alasan mengapa?
Maaf - tidak ada yang jelas muncul dalam pikiran.
Untuk masalah pertama, saya akan merekomendasikan melihat kueri SQL yang dihasilkan. Pastikan filter suspended
dan abandoned
benar-benar diterapkan.
Untuk masalah kedua, saya akan memeriksa data yang masuk. Ada kemungkinan bahwa nilai yang tidak valid diberikan ke filter suspended
dan abandoned
saat mengubah halaman.
Saya memasukkan beberapa pernyataan cetak dan saya menemukan yang berikut:
def __init__(self, data=None, *args, **kwargs):
if data is not None: # 1
data = data.copy()
for name, f in self.base_filters.items():
initial = f.extra.get('initial')
# filter param is either missing or empty, use initial as default
if not data.get(name) and initial:
data[name] = initial
super(BaseFilterSet, self).__init__(data, *args, **kwargs)
Jadi sepertinya data
adalah None
. Akankah Anda mengetahui mengapa tampilan berbasis kelas saya tidak meneruskan data
ke AccountFilter
?
Hm. Argumen data
harus selalu disediakan oleh FilterView
.
Apakah data
kosong untuk halaman pertama dan kedua?
Ini tidak dapat dialamatkan sebagaimana adanya. Menutup info yang cukup tertunda untuk mengidentifikasi masalah.
Masalah yang sama di sini setelah memutakhirkan ke 2.0. Halaman default atau filter kosong harus ada di URL untuk mendapatkan hasilnya. Apakah ini setidaknya didokumentasikan di suatu tempat?
Masih membutuhkan lebih banyak info untuk dapat mereproduksi ...
page
? Bukankah ini berkaitan dengan pagination Anda, daripada Filter Django?
Info apa yang dibutuhkan sebenarnya? Upgrade ke 2.0 mengarah ke perilaku yang dijelaskan. Menurunkan versi ke 1.1.0 membuat semuanya kembali normal. Saya mencoba menyederhanakan tampilan dan filter set seminimal mungkin, perilakunya tetap ada, jadi sepertinya ini cukup mudah untuk direproduksi.
@moorchegue , contoh kasus uji atau proyek uji minimal yang menunjukkan masalah ini akan sangat membantu.
Sepertinya masalahnya ada pada apa pun yang menyediakan logika pagination Anda. Ya, mungkin ada beberapa ketidakcocokan dengan versi baru, tetapi masalah debug di paket lain berada di luar jangkauan. Anda perlu mendemonstrasikan bug di Django Filter agar ada apapun yang bisa kita lakukan di sini.
Oke, jadi masalahnya di sini adalah dengan metode is_valid()
yang diperkenalkan sebagai bagian dari #788.
Ini secara otomatis mengembalikan False
ketika data
adalah None
.
Dalam tampilan kami kemudian mengatur object_list
ke qs.none()
.
Oleh karena itu perilaku yang diamati.
Pengujian untuk ini tidak gagal karena template pengujian menggunakan filter.qs
daripada object_list
.
Solusi langsungnya adalah menyetel strict = False
pada filterset Anda. Ini memiliki konsekuensi bahwa parameter filter tidak valid yang sebenarnya akan mengarah ke pemfilteran sebagian daripada menampilkan hasil kosong, tetapi seharusnya bisa diterapkan untuk saat ini. (Lebih baik mengesampingkan logika tampilan get
tentu saja ...)
Kami akan memikirkan dan meningkatkan penanganan untuk kasus yang tidak terikat.
Hm. Kekurangan utama di sini adalah perbedaan antara object_list
dan .qs
FilterSet. Memindahkan perilaku ketat kembali ke FilterSet.qs
akan memperbaikinya.
Selain itu, tidak ada penanganan yang ketat/tidak ketat untuk backend DRF.
Saya akan menghapus ini.
@rpkilby Apakah ada kemajuan dalam masalah ini?
Yap - memulai PR tetapi harus menunda pekerjaan open source saya. Saya harus bisa melanjutkan di mana saya tinggalkan segera.
Perhatikan bahwa solusinya adalah dengan mengatur strict = False
pada FilterMixin
turunan Anda (mungkin View
.
Tidak bisakah Anda mengubah kondisi untuk mengembalikan qs jika bentuk tidak terbatas?
misalnya
- if self.filterset.is_valid() or not self.get_strict():
+ if not self.filterset.is_bound or self.filterset.is_valid() or not self.get_strict():
https://github.com/carltongibson/django-filter/pull/1007
Terima kasih.
Komentar yang paling membantu
Yap - memulai PR tetapi harus menunda pekerjaan open source saya. Saya harus bisa melanjutkan di mana saya tinggalkan segera.