We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
async serializer: also set is_deleted to True for blocked comments
**URL:** 
**user:** 
**expected behaviour:** readable code, comments should have distinctive properties with distinct names, meanings and behavior
**behaviour:** **Async comments** have the properties `is_removed` and `is_deleted`. Comments that are either removed (by a moderator) or deleted (by a creator) are both set to `is_deleted` and their content is permanently deleted.
**important screensize:**
**device & browser:** 
**Comment/Question:** 
Because the serializer does not differentiate between moderator and creator for deleting the comment, does it actually make sense to show this differentiation in the serializer?
This is related to #902 and #903
Screenshot?


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `adhocracy4/comments_async/serializers.py`
Content:
```
1 from django.conf import settings
2 from django.contrib.contenttypes.models import ContentType
3 from django.utils.translation import gettext as _
4 from easy_thumbnails.files import get_thumbnailer
5 from rest_framework import serializers
6 
7 from adhocracy4.comments.models import Comment
8 
9 
10 class CommentSerializer(serializers.ModelSerializer):
11     """Default Serializer for the comments."""
12 
13     user_name = serializers.SerializerMethodField()
14     user_pk = serializers.SerializerMethodField()
15     user_profile_url = serializers.SerializerMethodField()
16     user_image = serializers.SerializerMethodField()
17     is_deleted = serializers.SerializerMethodField()
18     ratings = serializers.SerializerMethodField()
19     is_moderator = serializers.SerializerMethodField()
20     comment_content_type = serializers.SerializerMethodField()
21     has_rating_permission = serializers.SerializerMethodField()
22     has_changing_permission = serializers.SerializerMethodField()
23     has_deleting_permission = serializers.SerializerMethodField()
24 
25     class Meta:
26         model = Comment
27         read_only_fields = ('modified', 'created', 'id',
28                             'user_name', 'user_pk', 'user_image',
29                             'user_image_fallback', 'ratings',
30                             'content_type', 'object_pk',
31                             'comment_content_type', 'has_rating_permission',
32                             'has_changing_permission',
33                             'has_deleting_permission')
34         exclude = ('creator',)
35 
36     def to_representation(self, instance):
37         """
38         Create a dictionary form categories and don't show blocked comments.
39 
40         Gets the categories and adds them along with their values
41         to a dictionary.
42         Also gets the comments and blocks their content
43         from being shown if they are set to blocked.
44         """
45         ret = super().to_representation(instance)
46         categories = {}
47         if ret['comment_categories']:
48             category_choices = getattr(settings,
49                                        'A4_COMMENT_CATEGORIES', '')
50             if category_choices:
51                 category_choices = dict((x, str(y)) for x, y
52                                         in category_choices)
53             category_list = ret['comment_categories'].strip('[]').split(',')
54             for category in category_list:
55                 if category in category_choices:
56                     categories[category] = category_choices[category]
57                 else:
58                     categories[category] = category
59         ret['comment_categories'] = categories
60         is_blocked = ret.get('is_blocked')
61         if is_blocked:
62             ret['comment'] = ''
63         return ret
64 
65     def to_internal_value(self, data):
66         data = super().to_internal_value(data)
67         if 'comment_categories' in data:
68             value = data.get('comment_categories')
69             if value == '' or value == '[]':
70                 raise serializers.ValidationError({
71                     'comment_categories': _('Please choose one or more '
72                                             'categories.')
73                 })
74         return data
75 
76     def get_user_pk(self, obj):
77         if (obj.is_censored or obj.is_removed):
78             return -1
79         return str(obj.creator.id)
80 
81     def get_user_profile_url(self, obj):
82         if obj.is_censored or obj.is_removed:
83             return ''
84         try:
85             return obj.creator.get_absolute_url()
86         except AttributeError:
87             return ''
88 
89     def get_user_name(self, obj):
90         """Don't show username if comment is marked removed or censored."""
91         if(obj.is_censored or obj.is_removed):
92             return _('unknown user')
93         return obj.creator.get_short_name()
94 
95     def get_user_image_fallback(self, obj):
96         """Load small thumbnail images for default user images."""
97         if(obj.is_censored or obj.is_removed):
98             return None
99         try:
100             if obj.creator.avatar_fallback:
101                 return obj.creator.avatar_fallback
102         except AttributeError:
103             pass
104         return None
105 
106     def get_user_image(self, obj):
107         """Load small thumbnail images for user images."""
108         if(obj.is_censored or obj.is_removed):
109             return None
110         try:
111             if obj.creator.avatar:
112                 avatar = get_thumbnailer(obj.creator.avatar)['avatar']
113                 return avatar.url
114         except AttributeError:
115             pass
116         return self.get_user_image_fallback(obj)
117 
118     def get_is_moderator(self, obj):
119         return obj.project.has_moderator(obj.creator)
120 
121     def get_is_deleted(self, obj):
122         """Return true if one of the flags is set."""
123         return (obj.is_censored or obj.is_removed)
124 
125     def get_ratings(self, comment):
126         """
127         Get positive and negative rating count.
128 
129         As well as info on the request users rating
130         """
131         user = self.context['request'].user
132         positive_ratings = comment.ratings.filter(value=1).count()
133         negative_ratings = comment.ratings.filter(value=-1).count()
134 
135         if user.is_authenticated:
136             user_rating = comment.ratings.filter(creator=user).first()
137         else:
138             user_rating = None
139 
140         if user_rating:
141             user_rating_value = user_rating.value
142             user_rating_id = user_rating.pk
143         else:
144             user_rating_value = None
145             user_rating_id = None
146 
147         result = {
148             'positive_ratings': positive_ratings,
149             'negative_ratings': negative_ratings,
150             'current_user_rating_value': user_rating_value,
151             'current_user_rating_id': user_rating_id
152         }
153 
154         return result
155 
156     # used in zt-app, where we can't pass props through template tags
157     # FIXME: this should replace comments_contenttype passed in template tag
158     def get_comment_content_type(self, comment):
159         return ContentType.objects.get_for_model(Comment).pk
160 
161     def get_has_rating_permission(self, comment):
162         request = self.context.get('request')
163         if request and hasattr(request, 'user'):
164             user = request.user
165             return user.has_perm('a4comments.rate_comment', comment)
166         return False
167 
168     def get_has_changing_permission(self, comment):
169         request = self.context.get('request')
170         if request and hasattr(request, 'user'):
171             user = request.user
172             return user.has_perm('a4comments.change_comment', comment)
173         return False
174 
175     def get_has_deleting_permission(self, comment):
176         request = self.context.get('request')
177         if request and hasattr(request, 'user'):
178             user = request.user
179             return user.has_perm('a4comments.delete_comment', comment)
180         return False
181 
182 
183 class CommentListSerializer(CommentSerializer):
184     """Serializer for the comments to be used when viewed as list."""
185 
186 
187 class ThreadSerializer(CommentSerializer):
188     """Serializes a comment including child comment (replies)."""
189 
190     child_comments = CommentSerializer(many=True, read_only=True)
191 
192 
193 class ThreadListSerializer(CommentListSerializer):
194     """
195     Serializes comments when viewed.
196 
197     As list including child comment (replies).
198     """
199 
200     child_comments = CommentListSerializer(many=True, read_only=True)
201
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/adhocracy4/comments_async/serializers.py b/adhocracy4/comments_async/serializers.py
--- a/adhocracy4/comments_async/serializers.py
+++ b/adhocracy4/comments_async/serializers.py
@@ -31,16 +31,15 @@
 
     def to_representation(self, instance):
         """
-        Create a dictionary form categories and don't show blocked comments.
+        Create a dictionary from categories and don't show blocked comments.
 
         Gets the categories and adds them along with their values
-        to a dictionary.
-        Also gets the comments and blocks their content
-        from being shown if they are set to blocked.
+        to a dictionary. Do return empty dict when comment is_blocked.
+        Does return empty string as comment text when comment is_blocked.
         """
         ret = super().to_representation(instance)
         categories = {}
-        if ret['comment_categories']:
+        if ret['comment_categories'] and not instance.is_blocked:
             category_choices = getattr(settings,
                                        'A4_COMMENT_CATEGORIES', '')
             if category_choices:
@@ -53,8 +52,7 @@
                 else:
                     categories[category] = category
         ret['comment_categories'] = categories
-        is_blocked = ret.get('is_blocked')
-        if is_blocked:
+        if instance.is_blocked:
             ret['comment'] = ''
         return ret
 
@@ -70,12 +68,12 @@
         return data
 
     def get_user_pk(self, obj):
-        if (obj.is_censored or obj.is_removed):
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return -1
         return str(obj.creator.id)
 
     def get_user_profile_url(self, obj):
-        if obj.is_censored or obj.is_removed:
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return ''
         try:
             return obj.creator.get_absolute_url()
@@ -84,13 +82,13 @@
 
     def get_user_name(self, obj):
         """Don't show username if comment is marked removed or censored."""
-        if(obj.is_censored or obj.is_removed):
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return _('unknown user')
         return obj.creator.get_short_name()
 
     def get_user_image_fallback(self, obj):
         """Load small thumbnail images for default user images."""
-        if(obj.is_censored or obj.is_removed):
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return None
         try:
             if obj.creator.avatar_fallback:
@@ -101,7 +99,7 @@
 
     def get_user_image(self, obj):
         """Load small thumbnail images for user images."""
-        if(obj.is_censored or obj.is_removed):
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return None
         try:
             if obj.creator.avatar:
@@ -116,7 +114,7 @@
 
     def get_is_deleted(self, obj):
         """Return true if one of the flags is set."""
-        return (obj.is_censored or obj.is_removed)
+        return obj.is_censored or obj.is_removed or obj.is_blocked
 
     def get_ratings(self, comment):
         """

{"golden_diff": "diff --git a/adhocracy4/comments_async/serializers.py b/adhocracy4/comments_async/serializers.py\n--- a/adhocracy4/comments_async/serializers.py\n+++ b/adhocracy4/comments_async/serializers.py\n@@ -31,16 +31,15 @@\n \n     def to_representation(self, instance):\n         \"\"\"\n-        Create a dictionary form categories and don't show blocked comments.\n+        Create a dictionary from categories and don't show blocked comments.\n \n         Gets the categories and adds them along with their values\n-        to a dictionary.\n-        Also gets the comments and blocks their content\n-        from being shown if they are set to blocked.\n+        to a dictionary. Do return empty dict when comment is_blocked.\n+        Does return empty string as comment text when comment is_blocked.\n         \"\"\"\n         ret = super().to_representation(instance)\n         categories = {}\n-        if ret['comment_categories']:\n+        if ret['comment_categories'] and not instance.is_blocked:\n             category_choices = getattr(settings,\n                                        'A4_COMMENT_CATEGORIES', '')\n             if category_choices:\n@@ -53,8 +52,7 @@\n                 else:\n                     categories[category] = category\n         ret['comment_categories'] = categories\n-        is_blocked = ret.get('is_blocked')\n-        if is_blocked:\n+        if instance.is_blocked:\n             ret['comment'] = ''\n         return ret\n \n@@ -70,12 +68,12 @@\n         return data\n \n     def get_user_pk(self, obj):\n-        if (obj.is_censored or obj.is_removed):\n+        if obj.is_censored or obj.is_removed or obj.is_blocked:\n             return -1\n         return str(obj.creator.id)\n \n     def get_user_profile_url(self, obj):\n-        if obj.is_censored or obj.is_removed:\n+        if obj.is_censored or obj.is_removed or obj.is_blocked:\n             return ''\n         try:\n             return obj.creator.get_absolute_url()\n@@ -84,13 +82,13 @@\n \n     def get_user_name(self, obj):\n         \"\"\"Don't show username if comment is marked removed or censored.\"\"\"\n-        if(obj.is_censored or obj.is_removed):\n+        if obj.is_censored or obj.is_removed or obj.is_blocked:\n             return _('unknown user')\n         return obj.creator.get_short_name()\n \n     def get_user_image_fallback(self, obj):\n         \"\"\"Load small thumbnail images for default user images.\"\"\"\n-        if(obj.is_censored or obj.is_removed):\n+        if obj.is_censored or obj.is_removed or obj.is_blocked:\n             return None\n         try:\n             if obj.creator.avatar_fallback:\n@@ -101,7 +99,7 @@\n \n     def get_user_image(self, obj):\n         \"\"\"Load small thumbnail images for user images.\"\"\"\n-        if(obj.is_censored or obj.is_removed):\n+        if obj.is_censored or obj.is_removed or obj.is_blocked:\n             return None\n         try:\n             if obj.creator.avatar:\n@@ -116,7 +114,7 @@\n \n     def get_is_deleted(self, obj):\n         \"\"\"Return true if one of the flags is set.\"\"\"\n-        return (obj.is_censored or obj.is_removed)\n+        return obj.is_censored or obj.is_removed or obj.is_blocked\n \n     def get_ratings(self, comment):\n         \"\"\"\n", "issue": "async serializer: also set is_deleted to True for blocked comments\n**URL:** \r\n**user:** \r\n**expected behaviour:** readable code, comments should have distinctive properties with distinct names, meanings and behavior\r\n**behaviour:** **Async comments** have the properties `is_removed` and `is_deleted`. Comments that are either removed (by a moderator) or deleted (by a creator) are both set to `is_deleted` and their content is permanently deleted.\r\n**important screensize:**\r\n**device & browser:** \r\n**Comment/Question:** \r\nBecause the serializer does not differentiate between moderator and creator for deleting the comment, does it actually make sense to show this differentiation in the serializer?\r\nThis is related to #902 and #903\r\nScreenshot?\r\n\n", "before_files": [{"content": "from django.conf import settings\nfrom django.contrib.contenttypes.models import ContentType\nfrom django.utils.translation import gettext as _\nfrom easy_thumbnails.files import get_thumbnailer\nfrom rest_framework import serializers\n\nfrom adhocracy4.comments.models import Comment\n\n\nclass CommentSerializer(serializers.ModelSerializer):\n    \"\"\"Default Serializer for the comments.\"\"\"\n\n    user_name = serializers.SerializerMethodField()\n    user_pk = serializers.SerializerMethodField()\n    user_profile_url = serializers.SerializerMethodField()\n    user_image = serializers.SerializerMethodField()\n    is_deleted = serializers.SerializerMethodField()\n    ratings = serializers.SerializerMethodField()\n    is_moderator = serializers.SerializerMethodField()\n    comment_content_type = serializers.SerializerMethodField()\n    has_rating_permission = serializers.SerializerMethodField()\n    has_changing_permission = serializers.SerializerMethodField()\n    has_deleting_permission = serializers.SerializerMethodField()\n\n    class Meta:\n        model = Comment\n        read_only_fields = ('modified', 'created', 'id',\n                            'user_name', 'user_pk', 'user_image',\n                            'user_image_fallback', 'ratings',\n                            'content_type', 'object_pk',\n                            'comment_content_type', 'has_rating_permission',\n                            'has_changing_permission',\n                            'has_deleting_permission')\n        exclude = ('creator',)\n\n    def to_representation(self, instance):\n        \"\"\"\n        Create a dictionary form categories and don't show blocked comments.\n\n        Gets the categories and adds them along with their values\n        to a dictionary.\n        Also gets the comments and blocks their content\n        from being shown if they are set to blocked.\n        \"\"\"\n        ret = super().to_representation(instance)\n        categories = {}\n        if ret['comment_categories']:\n            category_choices = getattr(settings,\n                                       'A4_COMMENT_CATEGORIES', '')\n            if category_choices:\n                category_choices = dict((x, str(y)) for x, y\n                                        in category_choices)\n            category_list = ret['comment_categories'].strip('[]').split(',')\n            for category in category_list:\n                if category in category_choices:\n                    categories[category] = category_choices[category]\n                else:\n                    categories[category] = category\n        ret['comment_categories'] = categories\n        is_blocked = ret.get('is_blocked')\n        if is_blocked:\n            ret['comment'] = ''\n        return ret\n\n    def to_internal_value(self, data):\n        data = super().to_internal_value(data)\n        if 'comment_categories' in data:\n            value = data.get('comment_categories')\n            if value == '' or value == '[]':\n                raise serializers.ValidationError({\n                    'comment_categories': _('Please choose one or more '\n                                            'categories.')\n                })\n        return data\n\n    def get_user_pk(self, obj):\n        if (obj.is_censored or obj.is_removed):\n            return -1\n        return str(obj.creator.id)\n\n    def get_user_profile_url(self, obj):\n        if obj.is_censored or obj.is_removed:\n            return ''\n        try:\n            return obj.creator.get_absolute_url()\n        except AttributeError:\n            return ''\n\n    def get_user_name(self, obj):\n        \"\"\"Don't show username if comment is marked removed or censored.\"\"\"\n        if(obj.is_censored or obj.is_removed):\n            return _('unknown user')\n        return obj.creator.get_short_name()\n\n    def get_user_image_fallback(self, obj):\n        \"\"\"Load small thumbnail images for default user images.\"\"\"\n        if(obj.is_censored or obj.is_removed):\n            return None\n        try:\n            if obj.creator.avatar_fallback:\n                return obj.creator.avatar_fallback\n        except AttributeError:\n            pass\n        return None\n\n    def get_user_image(self, obj):\n        \"\"\"Load small thumbnail images for user images.\"\"\"\n        if(obj.is_censored or obj.is_removed):\n            return None\n        try:\n            if obj.creator.avatar:\n                avatar = get_thumbnailer(obj.creator.avatar)['avatar']\n                return avatar.url\n        except AttributeError:\n            pass\n        return self.get_user_image_fallback(obj)\n\n    def get_is_moderator(self, obj):\n        return obj.project.has_moderator(obj.creator)\n\n    def get_is_deleted(self, obj):\n        \"\"\"Return true if one of the flags is set.\"\"\"\n        return (obj.is_censored or obj.is_removed)\n\n    def get_ratings(self, comment):\n        \"\"\"\n        Get positive and negative rating count.\n\n        As well as info on the request users rating\n        \"\"\"\n        user = self.context['request'].user\n        positive_ratings = comment.ratings.filter(value=1).count()\n        negative_ratings = comment.ratings.filter(value=-1).count()\n\n        if user.is_authenticated:\n            user_rating = comment.ratings.filter(creator=user).first()\n        else:\n            user_rating = None\n\n        if user_rating:\n            user_rating_value = user_rating.value\n            user_rating_id = user_rating.pk\n        else:\n            user_rating_value = None\n            user_rating_id = None\n\n        result = {\n            'positive_ratings': positive_ratings,\n            'negative_ratings': negative_ratings,\n            'current_user_rating_value': user_rating_value,\n            'current_user_rating_id': user_rating_id\n        }\n\n        return result\n\n    # used in zt-app, where we can't pass props through template tags\n    # FIXME: this should replace comments_contenttype passed in template tag\n    def get_comment_content_type(self, comment):\n        return ContentType.objects.get_for_model(Comment).pk\n\n    def get_has_rating_permission(self, comment):\n        request = self.context.get('request')\n        if request and hasattr(request, 'user'):\n            user = request.user\n            return user.has_perm('a4comments.rate_comment', comment)\n        return False\n\n    def get_has_changing_permission(self, comment):\n        request = self.context.get('request')\n        if request and hasattr(request, 'user'):\n            user = request.user\n            return user.has_perm('a4comments.change_comment', comment)\n        return False\n\n    def get_has_deleting_permission(self, comment):\n        request = self.context.get('request')\n        if request and hasattr(request, 'user'):\n            user = request.user\n            return user.has_perm('a4comments.delete_comment', comment)\n        return False\n\n\nclass CommentListSerializer(CommentSerializer):\n    \"\"\"Serializer for the comments to be used when viewed as list.\"\"\"\n\n\nclass ThreadSerializer(CommentSerializer):\n    \"\"\"Serializes a comment including child comment (replies).\"\"\"\n\n    child_comments = CommentSerializer(many=True, read_only=True)\n\n\nclass ThreadListSerializer(CommentListSerializer):\n    \"\"\"\n    Serializes comments when viewed.\n\n    As list including child comment (replies).\n    \"\"\"\n\n    child_comments = CommentListSerializer(many=True, read_only=True)\n", "path": "adhocracy4/comments_async/serializers.py"}], "after_files": [{"content": "from django.conf import settings\nfrom django.contrib.contenttypes.models import ContentType\nfrom django.utils.translation import gettext as _\nfrom easy_thumbnails.files import get_thumbnailer\nfrom rest_framework import serializers\n\nfrom adhocracy4.comments.models import Comment\n\n\nclass CommentSerializer(serializers.ModelSerializer):\n    \"\"\"Default Serializer for the comments.\"\"\"\n\n    user_name = serializers.SerializerMethodField()\n    user_pk = serializers.SerializerMethodField()\n    user_profile_url = serializers.SerializerMethodField()\n    user_image = serializers.SerializerMethodField()\n    is_deleted = serializers.SerializerMethodField()\n    ratings = serializers.SerializerMethodField()\n    is_moderator = serializers.SerializerMethodField()\n    comment_content_type = serializers.SerializerMethodField()\n    has_rating_permission = serializers.SerializerMethodField()\n\n    class Meta:\n        model = Comment\n        read_only_fields = ('modified', 'created', 'id',\n                            'user_name', 'user_pk', 'user_image',\n                            'user_image_fallback', 'ratings',\n                            'content_type', 'object_pk',\n                            'comment_content_type', 'has_rating_permission')\n        exclude = ('creator',)\n\n    def to_representation(self, instance):\n        \"\"\"\n        Create a dictionary from categories and don't show blocked comments.\n\n        Gets the categories and adds them along with their values\n        to a dictionary. Do return empty dict when comment is_blocked.\n        Does return empty string as comment text when comment is_blocked.\n        \"\"\"\n        ret = super().to_representation(instance)\n        categories = {}\n        if ret['comment_categories'] and not instance.is_blocked:\n            category_choices = getattr(settings,\n                                       'A4_COMMENT_CATEGORIES', '')\n            if category_choices:\n                category_choices = dict((x, str(y)) for x, y\n                                        in category_choices)\n            category_list = ret['comment_categories'].strip('[]').split(',')\n            for category in category_list:\n                if category in category_choices:\n                    categories[category] = category_choices[category]\n                else:\n                    categories[category] = category\n        ret['comment_categories'] = categories\n        if instance.is_blocked:\n            ret['comment'] = ''\n        return ret\n\n    def to_internal_value(self, data):\n        data = super().to_internal_value(data)\n        if 'comment_categories' in data:\n            value = data.get('comment_categories')\n            if value == '' or value == '[]':\n                raise serializers.ValidationError({\n                    'comment_categories': _('Please choose one or more '\n                                            'categories.')\n                })\n        return data\n\n    def get_user_pk(self, obj):\n        if obj.is_censored or obj.is_removed or obj.is_blocked:\n            return -1\n        return str(obj.creator.id)\n\n    def get_user_profile_url(self, obj):\n        if obj.is_censored or obj.is_removed or obj.is_blocked:\n            return ''\n        try:\n            return obj.creator.get_absolute_url()\n        except AttributeError:\n            return ''\n\n    def get_user_name(self, obj):\n        \"\"\"Don't show username if comment is marked removed or censored.\"\"\"\n        if obj.is_censored or obj.is_removed or obj.is_blocked:\n            return _('unknown user')\n        return obj.creator.get_short_name()\n\n    def get_user_image_fallback(self, obj):\n        \"\"\"Load small thumbnail images for default user images.\"\"\"\n        if obj.is_censored or obj.is_removed or obj.is_blocked:\n            return None\n        try:\n            if obj.creator.avatar_fallback:\n                return obj.creator.avatar_fallback\n        except AttributeError:\n            pass\n        return None\n\n    def get_user_image(self, obj):\n        \"\"\"Load small thumbnail images for user images.\"\"\"\n        if obj.is_censored or obj.is_removed or obj.is_blocked:\n            return None\n        try:\n            if obj.creator.avatar:\n                avatar = get_thumbnailer(obj.creator.avatar)['avatar']\n                return avatar.url\n        except AttributeError:\n            pass\n        return self.get_user_image_fallback(obj)\n\n    def get_is_moderator(self, obj):\n        return obj.project.has_moderator(obj.creator)\n\n    def get_is_deleted(self, obj):\n        \"\"\"Return true if one of the flags is set.\"\"\"\n        return obj.is_censored or obj.is_removed or obj.is_blocked\n\n    def get_ratings(self, comment):\n        \"\"\"\n        Get positive and negative rating count.\n\n        As well as info on the request users rating\n        \"\"\"\n        user = self.context['request'].user\n        positive_ratings = comment.ratings.filter(value=1).count()\n        negative_ratings = comment.ratings.filter(value=-1).count()\n\n        if user.is_authenticated:\n            user_rating = comment.ratings.filter(creator=user).first()\n        else:\n            user_rating = None\n\n        if user_rating:\n            user_rating_value = user_rating.value\n            user_rating_id = user_rating.pk\n        else:\n            user_rating_value = None\n            user_rating_id = None\n\n        result = {\n            'positive_ratings': positive_ratings,\n            'negative_ratings': negative_ratings,\n            'current_user_rating_value': user_rating_value,\n            'current_user_rating_id': user_rating_id\n        }\n\n        return result\n\n    # used in zt-app, where we can't pass props through template tags\n    # FIXME: this should replace comments_contenttype passed in template tag\n    def get_comment_content_type(self, comment):\n        return ContentType.objects.get_for_model(Comment).pk\n\n    def get_has_rating_permission(self, comment):\n        request = self.context.get('request')\n        if request and hasattr(request, 'user'):\n            user = request.user\n            return user.has_perm('a4comments.rate_comment', comment)\n        return False\n\n\nclass CommentListSerializer(CommentSerializer):\n    \"\"\"Serializer for the comments to be used when viewed as list.\"\"\"\n\n\nclass ThreadSerializer(CommentSerializer):\n    \"\"\"Serializes a comment including child comment (replies).\"\"\"\n\n    child_comments = CommentSerializer(many=True, read_only=True)\n\n\nclass ThreadListSerializer(CommentListSerializer):\n    \"\"\"\n    Serializes comments when viewed.\n\n    As list including child comment (replies).\n    \"\"\"\n\n    child_comments = CommentListSerializer(many=True, read_only=True)\n", "path": "adhocracy4/comments_async/serializers.py"}]}