Django-filter: [2.1.0] BaseCSVWidget.value_from_datadict — AttributeError: objek 'list' tidak memiliki atribut 'split'

Dibuat pada 12 Jul 2019  ·  15Komentar  ·  Sumber: carltongibson/django-filter

aku berlari ke…

Traceback (most recent call last):
  [..]
  File "/usr/local/lib/python3.7/site-packages/django/forms/forms.py", line 393, in _clean_fields
    value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
  File "/usr/local/lib/python3.7/site-packages/django_filters/widgets.py", line 201, in value_from_datadict
    return value.split(',')
AttributeError: 'list' object has no attribute 'split'

dan menemukan bahwa kode di …
https://github.com/carltongibson/django-filter/blob/1f47e36b614724a8735e0457fa511dcaf5448481/django_filters/widgets.py#L195 -L202
… tidak kuat sehubungan dengan super().value_from_datadict(data, files, name) mengembalikan daftar. Saya perlu men-debug ini lagi, tetapi mungkin Anda sudah tahu apa yang terjadi di sini?

Komentar yang paling membantu

Saya baru saja mengalami kesalahan ini dan penjelasannya terkubur di utas ini, jadi untuk rekap dan menyimpan pencarian panjang untuk pembaca masa depan:

ManyToMany field yang dideklarasikan di filterset_fields viewset tidak boleh berisi in

Peringatan saat runtime akan sangat dihargai.

Semua 15 komentar

Hai @moseb. Bisakah Anda menempelkan kode FilterSet yang Anda gunakan? Beberapa baris terakhir dari jejak kembali sudah cukup untuk menentukan mengapa Anda mencapai pengecualian ini.

Pelacakan balik penuh:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/wsgiref/handlers.py", line 137, in run
    self.result = application(self.environ, self.start_response)
  File "/usr/local/lib/python3.7/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
    return self.application(environ, start_response)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/wsgi.py", line 141, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 75, in get_response
    response = self._middleware_chain(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/utils/deprecation.py", line 94, in __call__
    response = response or self.get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/utils/deprecation.py", line 94, in __call__
    response = response or self.get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/utils/deprecation.py", line 94, in __call__
    response = response or self.get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/utils/deprecation.py", line 94, in __call__
    response = response or self.get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/utils/deprecation.py", line 94, in __call__
    response = response or self.get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/utils/deprecation.py", line 94, in __call__
    response = response or self.get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django_global_request/middleware.py", line 15, in __call__
    return self.get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 143, in _get_response
    response = response.render()
  File "/usr/local/lib/python3.7/site-packages/django/template/response.py", line 106, in render
    self.content = self.rendered_content
  File "/usr/local/lib/python3.7/site-packages/rest_framework/response.py", line 72, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "/usr/local/lib/python3.7/site-packages/rest_framework/renderers.py", line 733, in render
    context = self.get_context(data, accepted_media_type, renderer_context)
  File "/usr/local/lib/python3.7/site-packages/rest_framework/renderers.py", line 710, in get_context
    'filter_form': self.get_filter_form(data, view, request),
  File "/usr/local/lib/python3.7/site-packages/rest_framework/renderers.py", line 642, in get_filter_form
    html = backend().to_html(request, queryset, view)
  File "/usr/local/lib/python3.7/site-packages/rest_framework_filters/backends.py", line 52, in to_html
    return super().to_html(request, queryset, view)
  File "/usr/local/lib/python3.7/site-packages/django_filters/rest_framework/backends.py", line 105, in to_html
    return template.render(context, request)
  File "/usr/local/lib/python3.7/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.7/site-packages/crispy_forms/templatetags/crispy_forms_tags.py", line 199, in render
    c = self.get_render(context).flatten()
  File "/usr/local/lib/python3.7/site-packages/crispy_forms/templatetags/crispy_forms_tags.py", line 118, in get_render
    actual_form.form_html = helper.render_layout(actual_form, node_context, template_pack=self.template_pack)
  File "/usr/local/lib/python3.7/site-packages/crispy_forms/helper.py", line 308, in render_layout
    template_pack=template_pack
  File "/usr/local/lib/python3.7/site-packages/crispy_forms/layout.py", line 140, in render
    return self.get_rendered_fields(form, form_style, context, template_pack, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/crispy_forms/layout.py", line 104, in get_rendered_fields
    for field in self.fields
  File "/usr/local/lib/python3.7/site-packages/crispy_forms/layout.py", line 104, in <genexpr>
    for field in self.fields
  File "/usr/local/lib/python3.7/site-packages/crispy_forms/utils.py", line 148, in render_field
    html = template.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/defaulttags.py", line 309, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/defaulttags.py", line 309, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/defaulttags.py", line 302, in render
    match = condition.eval(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/defaulttags.py", line 876, in eval
    return self.value.resolve(context, ignore_failures=True)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 671, in resolve
    obj = self.var.resolve(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 796, in resolve
    value = self._resolve_lookup(context)
  File "/usr/local/lib/python3.7/site-packages/django/template/base.py", line 837, in _resolve_lookup
    current = getattr(current, bit)
  File "/usr/local/lib/python3.7/site-packages/django/forms/boundfield.py", line 74, in errors
    return self.form.errors.get(self.name, self.form.error_class())
  File "/usr/local/lib/python3.7/site-packages/django/forms/forms.py", line 180, in errors
    self.full_clean()
  File "/usr/local/lib/python3.7/site-packages/django/forms/forms.py", line 381, in full_clean
    self._clean_fields()
  File "/usr/local/lib/python3.7/site-packages/django/forms/forms.py", line 393, in _clean_fields
    value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
  File "/usr/local/lib/python3.7/site-packages/django_filters/widgets.py", line 201, in value_from_datadict
    return value.split(',')
AttributeError: 'list' object has no attribute 'split'
[12/Jul/2019 13:49:06] "GET /XXXXXXXX/?ordering=first_name HTTP/1.1" 500 59

Itu dari menelusuri daftar di mana Django-rest-framework menghasilkan kode.

Hai @moseb. Bisakah Anda menempelkan kode FilterSet yang Anda gunakan?

Sejujurnya, saya belum menemukan apa pun di area kode itu. Mungkin semua oleh DRF. Belum yakin.
Saya sadar laporan bug saya tidak ideal, tetapi ini yang terbaik yang saya miliki saat ini. Maaf!

Tampilan API Anda harus memiliki filterset_class atau filterset_fields , atau jika Anda menggunakan versi lama dari django-filter, filter_class dan filter_fields .

Saya menemukan penggunaan filter_class — jadi saya kira Anda baru saja membantu saya menemukan bahwa migrasi ke Django-filter 2.0 tidak dilakukan dengan benar sampai akhir. Dingin!
Apakah ada sesuatu yang menghentikan Django-filter dari mendeteksi sisa makanan sebelum-2.x dan memperingatkannya, secara konseptual? Apakah itu memperingatkan tetapi saya melewatkannya? Apakah peringatan kode tentang ini akan menjadi tambahan sambutan untuk permintaan tarik?

v2.0 menghapus banyak peringatan penghentian yang ada, jadi Anda dapat mencoba menjalankan rangkaian pengujian Anda terhadap v1.0 dan kemudian v1.1 dari Django-filter.

Dengan asumsi ini akan menyelesaikan sendiri ketika Anda memperbarui. Kembalilah jika tidak.

Ada demo masalah yang dapat direproduksi sekarang di https://github.com/moseb/Django-filter-issue-1103-demo. Harap pertimbangkan untuk membuka kembali masalah ini. Terima kasih!

Ah, ini terkait dengan ModelMultipleChoiceFilter yang tidak kompatibel dengan mixin CSV, serta pencarian in . Dua masalah terpisah tetapi terkait di sini.

Anda tidak perlu mencari in untuk bidang m2m, karena filter pilihan ganda sudah menyediakan perilaku serupa.

Hai!

Ah, ini terkait dengan ModelMultipleChoiceFilter yang tidak kompatibel dengan mixin CSV, serta pencarian in . Dua masalah terpisah tetapi terkait di sini.

Apakah sudah ada tiket di GitHub untuk masalah ini?

Kedengarannya seperti membuat BaseCSVWidget.value_from_datadict lebih kuat seperti yang disebutkan di atas saja tidak akan memperbaiki masalah? (Saya belum sepenuhnya memahami masalah ini.)

Anda tidak perlu mencari in untuk bidang m2m, karena filter pilihan ganda sudah menyediakan perilaku serupa.

in memungkinkan pemeriksaan terhadap beberapa nilai lebih dari exact . Jika saya tidak dapat menggunakan ìn , bagaimana cara memeriksa beberapa nilai?

PS: Bisakah kita membuka kembali tiket ini?

Kedengarannya seperti membuat BaseCSVWidget.value_from_datadict lebih kuat seperti yang disebutkan di atas saja tidak akan memperbaiki masalah? (Saya belum sepenuhnya memahami masalah ini.)

Mungkin. Jika nilainya sudah menjadi daftar, itu harus dilanjutkan dan mengembalikan daftar itu. Karena itu, menurut saya tidak masuk akal untuk mencampur perilaku CSV dengan widget SelectMultiple .

in memungkinkan pemeriksaan terhadap beberapa nilai lebih dari exact . Jika saya tidak dapat menggunakan ìn , bagaimana cara memeriksa beberapa nilai?

ModelMultipleChoiceFilter membuat kueri OR dari objek Q. Jadi, jika Anda memiliki string kueri seperti /api/mymodel?m2m=a&m2m=b , Anda akan berakhir dengan panggilan filter seperti

MyModel.objects.filter(Q(m2m='a') | Q(m2m='b'))

Dengan rilis 2.1, lookup_expr sekarang diterapkan ke setiap objek Q, jadi Anda akan mendapatkan

MyModel.objects.filter(Q(m2m__in='a') | Q(m2m__in='b'))

Di atas tidak valid dan akan rusak, namun masuk akal untuk contains dan pencarian lain yang dimaksudkan untuk bekerja dengan nilai tunggal.

Jadi, singkatnya, yang perlu Anda lakukan di sini adalah menggunakan pencarian exact untuk bidang m2m Anda.


Saya pikir yang harus dilakukan di sini adalah:

  • Jadikan BaseCSVWidget kompatibel dengan SelectMultiple dengan mengembalikan nilainya jika sudah menjadi daftar. Atau jika seharusnya tidak kompatibel, setidaknya kita harus memberikan kesalahan yang berguna pada init.
  • Perbaiki Meta.fields untuk m2m. Membuat pencarian in untuk ModelMultipleChoiceFilter tidak masuk akal. Kita juga harus menguji apa yang terjadi untuk pencarian lain seperti isnull , yang mengharapkan boolean.

Ya, ini masih tidak terlihat seperti bug tetapi cara kerjanya sedang didokumentasikan, saya kira ...

Saya baru saja mengalami kesalahan ini dan penjelasannya terkubur di utas ini, jadi untuk rekap dan menyimpan pencarian panjang untuk pembaca masa depan:

ManyToMany field yang dideklarasikan di filterset_fields viewset tidak boleh berisi in

Peringatan saat runtime akan sangat dihargai.

@marcosox Ide bagus. Senang melihat PR menambahkan itu!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

loganknecht picture loganknecht  ·  4Komentar

sassanh picture sassanh  ·  4Komentar

gsvr picture gsvr  ·  3Komentar

hakib picture hakib  ·  3Komentar

chromakey picture chromakey  ·  5Komentar