Django-filter: [2.1.0] BaseCSVWidget.value_from_datadict - خطأ في السمة: كائن "القائمة" ليس له سمة "تقسيم"

تم إنشاؤها على ١٢ يوليو ٢٠١٩  ·  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) . أحتاج إلى تصحيح هذا الأمر أكثر ولكن ربما تعرف بالفعل ما الذي يحدث هنا؟

التعليق الأكثر فائدة

لقد حصلت للتو على هذا الخطأ وتفسيره مدفون في هذا الموضوع ، لذا لتلخيص وحفظ بحث طويل عن القراء في المستقبل:

الحقول ManyToMany المعلنة في مجموعات العرض ' filterset_fields يجب ألا تحتوي على 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. لست متأكدا بعد.
أدرك أن تقرير الخطأ الخاص بي ليس مثاليًا ولكنه أفضل ما لدي الآن. آسف!

يجب أن يكون عرض واجهة برمجة التطبيقات إما filterset_class أو filterset_fields ، أو إذا كنت تستخدم إصدارًا أقدم من مرشح django ، filter_class و filter_fields .

لقد اكتشفت استخدام filter_class - لذا أعتقد أنك ساعدتني للتو في العثور على أن الترحيل إلى django-filter 2.0 لم يتم بشكل صحيح حتى نهايته. رائع!
هل هناك شيء يمنع django-filter من اكتشاف بقايا الطعام قبل 2.x والتحذير منها ، من الناحية المفاهيمية؟ هل يحذر ولكن فاتني؟ هل رمز التحذير بشأن هذه إضافة مرحب بها لطلب السحب؟

أزال الإصدار 2.0 الكثير من تحذيرات الإيقاف الحالية ، لذلك قد تحاول تشغيل مجموعة الاختبار الخاصة بك مقابل v1.0 ثم v1.1 من django-filter.

على افتراض أن هذا سيحل نفسه عند التحديث. عد إذا لم يكن كذلك.

يوجد عرض توضيحي قابل لإعادة الإنتاج للمشكلة الآن على https://github.com/moseb/django-filter-issue-1103-demo. يرجى النظر في إعادة فتح هذه المشكلة. شكرا لك!

آه ، هذا مرتبط بعدم توافق ModelMultipleChoiceFilter مع مزيج CSV ، بالإضافة إلى in lookup. قضيتان منفصلتان ولكن مرتبطتان هنا.

لا يجب أن تحتاج إلى بحث in لحقول m2m ، لأن مرشح الاختيار من متعدد يوفر بالفعل سلوكًا مشابهًا.

مرحبا!

آه ، هذا مرتبط بعدم توافق ModelMultipleChoiceFilter مع مزيج CSV ، بالإضافة إلى in lookup. قضيتان منفصلتان ولكن مرتبطتان هنا.

هل توجد تذاكر حالية على GitHub لهذه المشكلات؟

يبدو أن جعل BaseCSVWidget.value_from_datadict أكثر قوة كما هو مذكور أعلاه وحده لن يحل المشكلة؟ (لم أفهم المشكلة تمامًا حتى الآن).

لا يجب أن تحتاج إلى بحث in لحقول m2m ، لأن مرشح الاختيار من متعدد يوفر بالفعل سلوكًا مشابهًا.

يسمح in بالتحقق من قيم متعددة تزيد عن exact . إذا لم أتمكن من استخدام ìn ، كيف يمكنني التحقق من القيم المتعددة؟

ملاحظة: هل يمكننا إعادة فتح هذه التذكرة؟

يبدو أن جعل BaseCSVWidget.value_from_datadict أكثر قوة كما هو مذكور أعلاه وحده لن يحل المشكلة؟ (لم أفهم المشكلة تمامًا حتى الآن).

ربما. إذا كانت القيمة قائمة بالفعل ، فيجب أن تمضي قدمًا وتعيد تلك القائمة. ومع ذلك ، لا أعتقد أنه من المنطقي خلط سلوك CSV مع عنصر واجهة المستخدم SelectMultiple .

يسمح in بالتحقق من قيم متعددة تزيد عن exact . إذا لم أتمكن من استخدام ìn ، كيف يمكنني التحقق من القيم المتعددة؟

ينشئ ModelMultipleChoiceFilter استعلام OR من كائنات Q. لذلك ، إذا كان لديك سلسلة استعلام مثل /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 وعمليات البحث الأخرى التي تهدف إلى العمل مع قيم فردية.

لذلك ، باختصار ، كل ما عليك فعله هنا هو استخدام exact للبحث عن حقل m2m الخاص بك.


أعتقد أن ما يجب فعله هنا هو:

  • اجعل BaseCSVWidget متوافقًا مع SelectMultiple بإرجاع القيمة إذا كانت قائمة بالفعل. أو إذا لم يكن متوافقًا ، فيجب على الأقل تقديم خطأ مفيد في init.
  • إصلاح Meta.fields للمتر المربع. إنشاء بحث in عن ModelMultipleChoiceFilter أمر غير منطقي. يجب علينا أيضًا اختبار ما يحدث لعمليات البحث الأخرى مثل isnull ، والتي تتوقع قيمة منطقية.

نعم ، لا يزال هذا لا يبدو وكأنه خطأ ولكن كيف يعمل كل شيء تحت التوثيق على ما أعتقد ...

لقد حصلت للتو على هذا الخطأ وتفسيره مدفون في هذا الموضوع ، لذا لتلخيص وحفظ بحث طويل عن القراء في المستقبل:

الحقول ManyToMany المعلنة في مجموعات العرض ' filterset_fields يجب ألا تحتوي على in

تحذير في وقت التشغيل سيكون موضع تقدير كبير.

marcosox فكرة جيدة. سعيد لإلقاء نظرة على العلاقات العامة مضيفا ذلك!

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات