Repository: digitalfabrik/integreat-cms

Issue:
TypeError in language tree ('NoneType' object is not iterable)
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
When navigating to the language tree, a type error occurs.

### Steps to Reproduce

1. Go to a region
2. Open language tree

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
The  tree view of the language tree should appear.

### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
The following traceback appears:
```
Environment:


Request Method: GET
Request URL: http://localhost:8000/augsburg/language-tree/

Django Version: 2.2.13
Python Version: 3.7.8
Installed Applications:
['cms.apps.CmsConfig',
 'gvz_api.apps.GvzApiConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.messages',
 'django.contrib.sessions',
 'django.contrib.staticfiles',
 'compressor',
 'compressor_toolkit',
 'corsheaders',
 'widget_tweaks',
 'easy_thumbnails',
 'filer',
 'mptt',
 'rules.apps.AutodiscoverRulesConfig']
Installed Middleware:
['corsheaders.middleware.CorsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template /home/timo/job/integreat/django/src/cms/templates/_raw.html, error at line 0
   'NoneType' object is not iterable
   1 : {% load static %}
   2 : {% load i18n %}
   3 : {% load compress %}
   4 : <!DOCTYPE html>
   5 : <html>
   6 : <head>
   7 :     <meta charset="utf-8" />
   8 :     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
   9 :     <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no, user-scalable=no" />
   10 :     <title>{% trans 'Integreat Backend' %}</title>


Traceback:

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/views/generic/base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "/home/timo/job/integreat/django/src/cms/decorators.py" in wrap
  27.             return function(request, *args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/contrib/auth/mixins.py" in dispatch
  85.         return super().dispatch(request, *args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/views/generic/base.py" in dispatch
  97.         return handler(request, *args, **kwargs)

File "/home/timo/job/integreat/django/src/cms/views/language_tree/language_tree_view.py" in get
  28.                 'language_tree': language_tree

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/shortcuts.py" in render
  36.     content = loader.render_to_string(template_name, context, request, using=using)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader.py" in render_to_string
  62.     return template.render(context, request)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/backends/django.py" in render
  61.             return self.template.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  171.                     return self._render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  150.             return compiled_parent._render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  150.             return compiled_parent._render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  62.                 result = block.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  62.                 result = block.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/defaulttags.py" in render
  309.                 return nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/mptt/templatetags/mptt_tags.py" in render
  268.         bits = [self._render_node(context, node) for node in roots]

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/mptt/templatetags/mptt_tags.py" in <listcomp>
  268.         bits = [self._render_node(context, node) for node in roots]

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/mptt/templatetags/mptt_tags.py" in _render_node
  257.         for child in node.get_children():

Exception Type: TypeError at /augsburg/language-tree/
Exception Value: 'NoneType' object is not iterable
```


TypeError in language tree ('NoneType' object is not iterable)
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
When navigating to the language tree, a type error occurs.

### Steps to Reproduce

1. Go to a region
2. Open language tree

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
The  tree view of the language tree should appear.

### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
The following traceback appears:
```
Environment:


Request Method: GET
Request URL: http://localhost:8000/augsburg/language-tree/

Django Version: 2.2.13
Python Version: 3.7.8
Installed Applications:
['cms.apps.CmsConfig',
 'gvz_api.apps.GvzApiConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.messages',
 'django.contrib.sessions',
 'django.contrib.staticfiles',
 'compressor',
 'compressor_toolkit',
 'corsheaders',
 'widget_tweaks',
 'easy_thumbnails',
 'filer',
 'mptt',
 'rules.apps.AutodiscoverRulesConfig']
Installed Middleware:
['corsheaders.middleware.CorsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template /home/timo/job/integreat/django/src/cms/templates/_raw.html, error at line 0
   'NoneType' object is not iterable
   1 : {% load static %}
   2 : {% load i18n %}
   3 : {% load compress %}
   4 : <!DOCTYPE html>
   5 : <html>
   6 : <head>
   7 :     <meta charset="utf-8" />
   8 :     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
   9 :     <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no, user-scalable=no" />
   10 :     <title>{% trans 'Integreat Backend' %}</title>


Traceback:

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/views/generic/base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "/home/timo/job/integreat/django/src/cms/decorators.py" in wrap
  27.             return function(request, *args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/contrib/auth/mixins.py" in dispatch
  85.         return super().dispatch(request, *args, **kwargs)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/views/generic/base.py" in dispatch
  97.         return handler(request, *args, **kwargs)

File "/home/timo/job/integreat/django/src/cms/views/language_tree/language_tree_view.py" in get
  28.                 'language_tree': language_tree

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/shortcuts.py" in render
  36.     content = loader.render_to_string(template_name, context, request, using=using)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader.py" in render_to_string
  62.     return template.render(context, request)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/backends/django.py" in render
  61.             return self.template.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  171.                     return self._render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  150.             return compiled_parent._render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  150.             return compiled_parent._render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  62.                 result = block.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  62.                 result = block.nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/defaulttags.py" in render
  309.                 return nodelist.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/mptt/templatetags/mptt_tags.py" in render
  268.         bits = [self._render_node(context, node) for node in roots]

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/mptt/templatetags/mptt_tags.py" in <listcomp>
  268.         bits = [self._render_node(context, node) for node in roots]

File "/home/timo/job/integreat/django/.venv/lib/python3.7/site-packages/mptt/templatetags/mptt_tags.py" in _render_node
  257.         for child in node.get_children():

Exception Type: TypeError at /augsburg/language-tree/
Exception Value: 'NoneType' object is not iterable
```




Discussion:
This is an extremely strange problem, maybe even in the mptt library...
the function `node.get_children()` returns `None`, but if I print the return value inside the function just before it gets returned, it is a QuerySet... :exploding_head: 

`mptt_tags.py`
```
node_children = node.get_children()
print("return value outside get_children():")
print(node_children)
```

`models.py`
```
print("return value inside get_children():")
print(qs)
return qs
```

Result:
```
return value inside get_children():
<TreeQuerySet [<LanguageTreeNode: English>]>
return value outside get_children():
None
```
This is an extremely strange problem, maybe even in the mptt library...
the function `node.get_children()` returns `None`, but if I print the return value inside the function just before it gets returned, it is a QuerySet... :exploding_head: 

`mptt_tags.py`
```
node_children = node.get_children()
print("return value outside get_children():")
print(node_children)
```

`models.py`
```
print("return value inside get_children():")
print(qs)
return qs
```

Result:
```
return value inside get_children():
<TreeQuerySet [<LanguageTreeNode: English>]>
return value outside get_children():
None
```

Resolving patch:
diff --git a/src/cms/models/languages/language_tree_node.py b/src/cms/models/languages/language_tree_node.py
--- a/src/cms/models/languages/language_tree_node.py
+++ b/src/cms/models/languages/language_tree_node.py
@@ -119,35 +119,35 @@ def depth(self):
     # Explicitly define functions to show documentation of base model
     @raise_if_unsaved
     def get_ancestors(self, ascending=False, include_self=False):
-        super(LanguageTreeNode, self).get_ancestors(ascending, include_self)
+        return super(LanguageTreeNode, self).get_ancestors(ascending, include_self)
 
     # pylint: disable=useless-super-delegation
     @raise_if_unsaved
     def get_family(self):
-        super(LanguageTreeNode, self).get_family()
+        return super(LanguageTreeNode, self).get_family()
 
     @raise_if_unsaved
     def get_children(self):
-        super(LanguageTreeNode, self).get_children()
+        return super(LanguageTreeNode, self).get_children()
 
     @raise_if_unsaved
     def get_descendants(self, include_self=False):
-        super(LanguageTreeNode, self).get_descendants(include_self)
+        return super(LanguageTreeNode, self).get_descendants(include_self)
 
     def get_descendant_count(self):
-        super(LanguageTreeNode, self).get_descendant_count()
+        return super(LanguageTreeNode, self).get_descendant_count()
 
     @raise_if_unsaved
     def get_root(self):
-        super(LanguageTreeNode, self).get_root()
+        return super(LanguageTreeNode, self).get_root()
 
     # pylint: disable=useless-super-delegation
     def insert_at(self, target, position='first-child', save=False, allow_existing_pk=False, refresh_target=True):
-        super(LanguageTreeNode, self).insert_at(target, position, save, allow_existing_pk, refresh_target)
+        return super(LanguageTreeNode, self).insert_at(target, position, save, allow_existing_pk, refresh_target)
 
     # pylint: disable=useless-super-delegation
     def move_to(self, target, position='first-child'):
-        super(LanguageTreeNode, self).move_to(target, position)
+        return super(LanguageTreeNode, self).move_to(target, position)
 
     def __str__(self):
         """


Test patch: