Django-filter: [2.1.0] BaseCSVWidget.value_from_datadict — AttributeError: 'list'オブジェクトに属性 'split'がありません

作成日 2019年07月12日  ·  15コメント  ·  ソース: carltongibson/django-filter

私は遭遇しました…

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'

そして、コードが…
https://github.com/carltongibson/django-filter/blob/1f47e36b614724a8735e0457fa511dcaf5448481/django_filters/widgets.py#L195 -L202
…リストを返すsuper().value_from_datadict(data, files, name)に関しては堅牢ではありません。 これをさらにデバッグする必要がありますが、ここで何が起こっているかをすでに知っているかもしれません。

最も参考になるコメント

私はちょうどこのエラーが発生し、その説明はこのスレッドに埋もれているので、要約して、将来の読者のために長い検索を保存します。

ビューセットのfilterset_fieldsで宣言されたManyToManyフィールドには、 inを含めることはできません

実行時の警告をいただければ幸いです。

全てのコメント15件

こんにちは@moseb。 使用しているFilterSetコードを貼り付けることはできますか? トレースバックの最後の数行は、この例外が発生した理由を判別するのに十分です。

完全なトレースバック:

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

これは、django-rest-frameworkがコードを生成するリストを参照することによるものです。

こんにちは@moseb。 使用しているFilterSetコードを貼り付けることはできますか?

正直なところ、コードのその領域にはまだ何も見つかりませんでした。 それはすべてDRFによるものかもしれません。 まだ確かではない。
私のバグレポートは理想的ではないことは承知していますが、今のところ最高です。 ごめん!

APIビューには、 filterset_classまたはfilterset_fieldsのいずれかが含まれている必要があります。古いバージョンのdjango-filterを使用している場合は、 filter_classfilter_fieldsが必要です。

filter_classの使用を見つけたので、 django-filter2.0への移行が最後まで適切に行われていなかったことを見つけるのに役立ったと思います。 涼しい!
概念的に、django-filterが2.xより前の残り物を検出して警告するのを妨げるものはありますか? 警告しますが、見逃しましたか? これらに関するコード警告は、プルリクエストの追加として歓迎されますか?

v2.0は既存の非推奨警告の多くを削除したので、django-filterのv1.0、次にv1.1に対してテストスイートを実行してみてください。

これは、更新時に自動的に解決されると想定しています。 そうでない場合は戻ってきてください。

この問題の再現可能なデモがhttps://github.com/moseb/django-filter-issue-1103-demoにあります。 この問題を再開することを検討してください。 ありがとう!

ああ、これはModelMultipleChoiceFilterがCSVミックスインと互換性がないことと、 inルックアップに関連しています。 ここでは、2つの別個の関連する問題があります。

複数選択フィルターはすでに同様の動作を提供しているため、m2mフィールドのinルックアップは必要ありません。

こんにちは!

ああ、これはModelMultipleChoiceFilterがCSVミックスインと互換性がないことと、 inルックアップに関連しています。 ここでは、2つの別個の関連する問題があります。

これらの問題のGitHubに既存のチケットはありますか?

上記のようにBaseCSVWidget.value_from_datadictをより堅牢にすると、問題は解決しないようです。 (私はまだ問題を完全には理解していません。)

複数選択フィルターはすでに同様の動作を提供しているため、m2mフィールドのinルックアップは必要ありません。

inを使用すると、 exactを超える複数の値をチェックできます。 ìnを使用できない場合、複数の値を確認するにはどうすればよいですか?

PS:このチケットを再開できますか?

上記のようにBaseCSVWidget.value_from_datadictをより堅牢にすると、問題は解決しないようです。 (私はまだ問題を完全には理解していません。)

おそらく。 値がすでにリストである場合は、先に進んでそのリストを返す必要があります。 とはいえ、CSVの動作とSelectMultipleウィジェットを混在させるのは意味がないと思います。

inを使用すると、 exactを超える複数の値をチェックできます。 ìnを使用できない場合、複数の値を確認するにはどうすればよいですか?

ModelMultipleChoiceFilterは、QオブジェクトからORクエリを作成します。 したがって、 /api/mymodel?m2m=a&m2m=bのようなクエリ文字列がある場合は、次のようなフィルタ呼び出しが発生します。

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

2.1リリースでは、 lookup_exprが各Qオブジェクトに適用されるようになったため、最終的には次のようになります。

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

上記は無効であり、壊れますが、 containsおよび単一の値で機能することを目的としたその他のルックアップには意味があります。

つまり、ここで行う必要があるのは、m2mフィールドにexactルックアップを使用することだけです。


ここでのやることは次のとおりです。

  • すでにリストになっている場合は値を返すことで、 BaseCSVWidgetSelectMultipleと互換性のあるものにします。 または、互換性がない場合は、少なくともinitで有用なエラーを提供する必要があります。
  • m2mのMeta.fieldsを修正します。 ModelMultipleChoiceFilterinルックアップを生成することは無意味です。 また、ブール値を期待するisnullのような他のルックアップで何が起こるかをテストする必要があります。

ええ、これはまだバグのようには見えませんが、すべてがどのように機能するかは文書化されていると思います...

私はちょうどこのエラーが発生し、その説明はこのスレッドに埋もれているので、要約して、将来の読者のために長い検索を保存します。

ビューセットのfilterset_fieldsで宣言されたManyToManyフィールドには、 inを含めることはできません

実行時の警告をいただければ幸いです。

@marcosoxいい考えです。 それを追加するPRを見て幸せです!

このページは役に立ちましたか?
0 / 5 - 0 評価