Django django-filter で、ImportError: cannot import name flatatt が発生


Django を upgrade したところ、django-filter で以下のエラーが発生しました。
対処方法を記載します。

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 244, in _legacy_get_response
    response = middleware_method(request)
  File "/usr/local/lib/python2.7/site-packages/django/middleware/locale.py", line 24, in process_request
    i18n_patterns_used, prefixed_default_language = is_language_prefix_patterns_used(urlconf)
  File "/usr/local/lib/python2.7/site-packages/django/utils/lru_cache.py", line 100, in wrapper
    result = user_function(*args, **kwds)
  File "/usr/local/lib/python2.7/site-packages/django/conf/urls/i18n.py", line 29, in is_language_prefix_patterns_used
    for url_pattern in get_resolver(urlconf).url_patterns:
  File "/usr/local/lib/python2.7/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python2.7/site-packages/django/urls/resolvers.py", line 405, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/usr/local/lib/python2.7/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python2.7/site-packages/django/urls/resolvers.py", line 398, in urlconf_module
    return import_module(self.urlconf_name)
  File "/usr/local/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/var/www/site/blog/blog/urls.py", line 38, in <module>
    url("^xyz_monotalk_api/", include("mezzanine_api.urls")),
  File "/usr/local/lib/python2.7/site-packages/django/conf/urls/__init__.py", line 50, in include
    urlconf_module = import_module(urlconf_module)
  File "/usr/local/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/usr/local/lib/python2.7/site-packages/mezzanine_api/urls.py", line 4, in <module>
    from .views import UserViewSet, PostViewSet, CategoryViewSet, PageViewSet, SiteViewSet
  File "/usr/local/lib/python2.7/site-packages/mezzanine_api/views.py", line 7, in <module>
    import django_filters
  File "/usr/local/lib/python2.7/site-packages/django_filters/__init__.py", line 4, in <module>
    from .filterset import FilterSet
  File "/usr/local/lib/python2.7/site-packages/django_filters/filterset.py", line 17, in <module>
    from .filters import (Filter, CharFilter, BooleanFilter, BaseInFilter, BaseRangeFilter,
  File "/usr/local/lib/python2.7/site-packages/django_filters/filters.py", line 17, in <module>
    from .fields import (
  File "/usr/local/lib/python2.7/site-packages/django_filters/fields.py", line 14, in <module>
    from .widgets import RangeWidget, LookupTypeWidget, CSVWidget, BaseCSVWidget
  File "/usr/local/lib/python2.7/site-packages/django_filters/widgets.py", line 13, in <module>
    from django.forms.widgets import flatatt
ImportError: cannot import name flatatt    

Django の Version

  • 前のverion
    Django-1.10.6

  • Upgrade後のverison
    Django-1.11.4


原因

Django 1.11 compatibility issue - cannot import name flatatt · Issue #673 · carltongibson/django-filter
に記載がありました。
django-filter を upgrade すれば動くようなので、upgrade します。

% pip install -U django-filter
Collecting django-filter
  Downloading django_filter-1.0.4-py2.py3-none-any.whl (43kB)
    100% |████████████████████████████████| 51kB 5.5MB/s 
Installing collected packages: django-filter
  Found existing installation: django-filter 1.0.1
    Uninstalling django-filter-1.0.1:
      Successfully uninstalled django-filter-1.0.1
Successfully installed django-filter-1.0.4

エラーが解消されました。

Fix 1.11 flatatt import path · liqd/adhocracy4@f75a059
を見ると、flatatt のパッケージが django.forms.widgets から、django.forms.utils に移動されたようです。


flatatt の処理内容について

以下、テストモジュールで何をしているのか確認しました。
* django/test_utils.py at c651331b34b7c3841c126959e6e52879bc6f0834 · django/django

attribute 属性 の key、value を保持する辞書を、文字列に変換する処理のようです。
HTML に書き出す処理で使用しているのかと思います。

    def test_flatatt(self):
        ###########
        # flatatt #
        ###########

        self.assertEqual(flatatt({'id': "header"}), ' id="header"')
        self.assertEqual(flatatt({'class': "news", 'title': "Read this"}), ' class="news" title="Read this"')
        self.assertEqual(
            flatatt({'class': "news", 'title': "Read this", 'required': "required"}),
            ' class="news" required="required" title="Read this"'
        )
        self.assertEqual(
            flatatt({'class': "news", 'title': "Read this", 'required': True}),
            ' class="news" title="Read this" required'
        )
        self.assertEqual(
            flatatt({'class': "news", 'title': "Read this", 'required': False}),
            ' class="news" title="Read this"'
        )
        self.assertEqual(flatatt({'class': None}), '')
        self.assertEqual(flatatt({}), '')
以上です。

コメント