Browse Source

#702: another pass on codebase

Rafał Pitoń 8 years ago
parent
commit
f10cdd7408

+ 24 - 6
misago/categories/serializers.py

@@ -43,12 +43,30 @@ class CategorySerializer(serializers.ModelSerializer, MutableFields):
 
     class Meta:
         model = Category
-        fields = (
-            'id', 'parent', 'name', 'description', 'is_closed', 'threads', 'posts', 'last_post_on',
-            'last_thread_title', 'last_poster_name', 'css_class', 'is_read', 'subcategories',
-            'absolute_url', 'last_thread_url', 'last_post_url', 'last_poster_url', 'acl',
-            'api_url', 'level', 'lft', 'rght',
-        )
+        fields = [
+            'id',
+            'parent',
+            'name',
+            'description',
+            'is_closed',
+            'threads',
+            'posts',
+            'last_post_on',
+            'last_thread_title',
+            'last_poster_name',
+            'css_class',
+            'is_read',
+            'subcategories',
+            'absolute_url',
+            'last_thread_url',
+            'last_post_url',
+            'last_poster_url',
+            'acl',
+            'api_url',
+            'level',
+            'lft',
+            'rght',
+        ]
 
     def get_description(self, obj):
         if obj.description:

+ 3 - 3
misago/core/serializers.py

@@ -7,7 +7,7 @@ class MutableFields(object):
         class Meta(cls.Meta):
             pass
 
-        Meta.fields = tuple(fields)
+        Meta.fields = list(fields)
 
         return type(name, (cls, ), {'Meta': Meta})
 
@@ -24,7 +24,7 @@ class MutableFields(object):
         class Meta(cls.Meta):
             pass
 
-        Meta.fields = tuple(final_fields)
+        Meta.fields = list(final_fields)
 
         return type(name, (cls, ), {'Meta': Meta})
 
@@ -41,6 +41,6 @@ class MutableFields(object):
         class Meta(cls.Meta):
             pass
 
-        Meta.fields = tuple(final_fields)
+        Meta.fields = list(final_fields)
 
         return type(name, (cls, ), {'Meta': Meta})

+ 3 - 1
misago/core/testproject/serializers.py

@@ -5,7 +5,9 @@ class MockSerializer(serializers.Serializer):
     id = serializers.SerializerMethodField()
 
     class Meta:
-        fields = ('id', )
+        fields = [
+            'id',
+        ]
 
     def get_id(self, obj):
         return obj * 2

+ 15 - 5
misago/core/tests/test_serializers.py

@@ -73,8 +73,18 @@ class TestSerializer(serializers.ModelSerializer, MutableFields):
 
     class Meta:
         model = Thread
-        fields = (
-            'id', 'title', 'replies', 'has_unapproved_posts', 'started_on', 'last_post_on',
-            'last_post_is_event', 'last_post', 'last_poster_name', 'is_unapproved', 'is_hidden',
-            'is_closed', 'weight',
-        )
+        fields = [
+            'id',
+            'title',
+            'replies',
+            'has_unapproved_posts',
+            'started_on',
+            'last_post_on',
+            'last_post_is_event',
+            'last_post',
+            'last_poster_name',
+            'is_unapproved',
+            'is_hidden',
+            'is_closed',
+            'weight',
+        ]

+ 0 - 32
misago/core/tests/test_testmailsetup.py

@@ -1,32 +0,0 @@
-from django.core import mail
-from django.core.management import call_command
-from django.test import TestCase
-from django.utils.six import StringIO
-
-from misago.core.management.commands import testemailsetup
-
-
-class TestEmailSetupTests(TestCase):
-    def test_email_setup(self):
-        """command sets test email in outbox"""
-        command = testemailsetup.Command()
-
-        out = StringIO()
-        call_command(command, "t@mail.com", stdout=out)
-        command_output = out.getvalue().splitlines()[0].strip()
-
-        self.assertEqual(command_output, 'Test message was sent to t@mail.com')
-        self.assertEqual('Test Message', mail.outbox[0].subject)
-
-    def test_invalid_args(self):
-        """
-        there are no unhandled exceptions when command receives invalid args
-        """
-        command = testemailsetup.Command()
-
-        out = StringIO()
-        err = StringIO()
-
-        call_command(command, "bawww", stdout=out, stderr=err)
-        command_output = err.getvalue().splitlines()[-1].strip()
-        self.assertEqual(command_output, "This isn't valid e-mail address")

+ 5 - 1
misago/threads/forms.py

@@ -23,7 +23,11 @@ class SearchAttachmentsForm(forms.Form):
     is_orphan = forms.ChoiceField(
         label=_("State"),
         required=False,
-        choices=(('', _("All")), ('yes', _("Only orphaned")), ('no', _("Not orphaned")), ),
+        choices=[
+            ('', _("All")),
+            ('yes', _("Only orphaned")),
+            ('no', _("Not orphaned")),
+        ],
     )
 
     def filter_queryset(self, criteria, queryset):

+ 15 - 3
misago/threads/permissions/polls.py

@@ -35,19 +35,31 @@ class RolePermissionsForm(forms.Form):
         label=_("Can start polls"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Own threads")), (2, _("All threads")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Own threads")),
+            (2, _("All threads")),
+        ],
     )
     can_edit_polls = forms.TypedChoiceField(
         label=_("Can edit polls"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Own polls")), (2, _("All polls")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Own polls")),
+            (2, _("All polls")),
+        ],
     )
     can_delete_polls = forms.TypedChoiceField(
         label=_("Can delete polls"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Own polls")), (2, _("All polls")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Own polls")),
+            (2, _("All polls")),
+        ],
     )
     poll_edit_time = forms.IntegerField(
         label=_("Time limit for own polls edits, in minutes"),

+ 49 - 10
misago/threads/permissions/threads.py

@@ -88,7 +88,10 @@ class CategoryPermissionsForm(forms.Form):
         label=_("Can see threads"),
         coerce=int,
         initial=0,
-        choices=((0, _("Started threads")), (1, _("All threads")), ),
+        choices=[
+            (0, _("Started threads")),
+            (1, _("All threads")),
+        ],
     )
 
     can_start_threads = YesNoSwitch(label=_("Can start threads"))
@@ -98,7 +101,11 @@ class CategoryPermissionsForm(forms.Form):
         label=_("Can edit threads"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Own threads")), (2, _("All threads")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Own threads")),
+            (2, _("All threads")),
+        ],
     )
     can_hide_own_threads = forms.TypedChoiceField(
         label=_("Can hide own threads"),
@@ -108,7 +115,11 @@ class CategoryPermissionsForm(forms.Form):
         ),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Hide threads")), (2, _("Delete threads")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Hide threads")),
+            (2, _("Delete threads")),
+        ],
     )
     thread_edit_time = forms.IntegerField(
         label=_("Time limit for own threads edits, in minutes"),
@@ -120,14 +131,22 @@ class CategoryPermissionsForm(forms.Form):
         label=_("Can hide all threads"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Hide threads")), (2, _("Delete threads")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Hide threads")),
+            (2, _("Delete threads")),
+        ],
     )
 
     can_pin_threads = forms.TypedChoiceField(
         label=_("Can pin threads"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Locally")), (2, _("Globally")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Locally")),
+            (2, _("Globally")),
+        ],
     )
     can_close_threads = YesNoSwitch(label=_("Can close threads"))
     can_move_threads = YesNoSwitch(label=_("Can move threads"))
@@ -137,14 +156,22 @@ class CategoryPermissionsForm(forms.Form):
         label=_("Can edit posts"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Own posts")), (2, _("All posts")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Own posts")),
+            (2, _("All posts")),
+        ],
     )
     can_hide_own_posts = forms.TypedChoiceField(
         label=_("Can hide own posts"),
         help_text=_("Only last posts to thread made within edit time limit can be hidden."),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Hide posts")), (2, _("Delete posts")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Hide posts")),
+            (2, _("Delete posts")),
+        ],
     )
     post_edit_time = forms.IntegerField(
         label=_("Time limit for own post edits, in minutes"),
@@ -156,14 +183,22 @@ class CategoryPermissionsForm(forms.Form):
         label=_("Can hide all posts"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Hide posts")), (2, _("Delete posts")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Hide posts")),
+            (2, _("Delete posts")),
+        ],
     )
 
     can_see_posts_likes = forms.TypedChoiceField(
         label=_("Can see posts likes"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Number only")), (2, _("Number and list of likers")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Number only")),
+            (2, _("Number and list of likers")),
+        ],
     )
     can_like_posts = YesNoSwitch(
         label=_("Can like posts"),
@@ -189,7 +224,11 @@ class CategoryPermissionsForm(forms.Form):
         label=_("Can hide events"),
         coerce=int,
         initial=0,
-        choices=((0, _("No")), (1, _("Hide events")), (2, _("Delete events")), ),
+        choices=[
+            (0, _("No")),
+            (1, _("Hide events")),
+            (2, _("Delete events")),
+        ],
     )
 
 

+ 13 - 4
misago/threads/serializers/attachment.py

@@ -20,10 +20,19 @@ class AttachmentSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Attachment
-        fields = (
-            'id', 'filetype', 'post', 'uploaded_on', 'uploader_name', 'uploader_ip', 'filename',
-            'size', 'acl', 'is_image', 'url',
-        )
+        fields = [
+            'id',
+            'filetype',
+            'post',
+            'uploaded_on',
+            'uploader_name',
+            'uploader_ip',
+            'filename',
+            'size',
+            'acl',
+            'is_image',
+            'url',
+        ]
 
     def get_acl(self, obj):
         try:

+ 30 - 8
misago/threads/serializers/poll.py

@@ -27,10 +27,21 @@ class PollSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Poll
-        fields = (
-            'id', 'poster_name', 'posted_on', 'length', 'question', 'allowed_choices',
-            'allow_revotes', 'votes', 'is_public', 'acl', 'choices', 'api', 'url',
-        )
+        fields = [
+            'id',
+            'poster_name',
+            'posted_on',
+            'length',
+            'question',
+            'allowed_choices',
+            'allow_revotes',
+            'votes',
+            'is_public',
+            'acl',
+            'choices',
+            'api',
+            'url',
+        ]
 
     def get_api(self, obj):
         return {
@@ -75,7 +86,13 @@ class EditPollSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Poll
-        fields = ('length', 'question', 'allowed_choices', 'allow_revotes', 'choices', )
+        fields = [
+            'length',
+            'question',
+            'allowed_choices',
+            'allow_revotes',
+            'choices',
+        ]
 
     def validate_choices(self, choices):
         clean_choices = list(map(self.clean_choice, choices))
@@ -161,9 +178,14 @@ class EditPollSerializer(serializers.ModelSerializer):
 class NewPollSerializer(EditPollSerializer):
     class Meta:
         model = Poll
-        fields = (
-            'length', 'question', 'allowed_choices', 'allow_revotes', 'is_public', 'choices',
-        )
+        fields = [
+            'length',
+            'question',
+            'allowed_choices',
+            'allow_revotes',
+            'is_public',
+            'choices',
+        ]
 
     def validate_choices(self, choices):
         clean_choices = list(map(self.clean_choice, choices))

+ 5 - 1
misago/threads/serializers/pollvote.py

@@ -13,7 +13,11 @@ class PollVoteSerializer(serializers.Serializer):
     url = serializers.SerializerMethodField()
 
     class Meta:
-        fields = ('voted_on', 'username', 'url', )
+        fields = [
+            'voted_on',
+            'username',
+            'url',
+        ]
 
     def get_username(self, obj):
         return obj['voter_name']

+ 8 - 1
misago/threads/serializers/postedit.py

@@ -17,7 +17,14 @@ class PostEditSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = PostEdit
-        fields = ('id', 'edited_on', 'editor_name', 'editor_slug', 'diff', 'url', )
+        fields = [
+            'id',
+            'edited_on',
+            'editor_name',
+            'editor_slug',
+            'diff',
+            'url',
+        ]
 
     def get_diff(self, obj):
         return obj.get_diff()

+ 7 - 1
misago/threads/serializers/postlike.py

@@ -18,7 +18,13 @@ class PostLikeSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = PostLike
-        fields = ('id', 'liked_on', 'liker_id', 'username', 'url', )
+        fields = [
+            'id',
+            'liked_on',
+            'liker_id',
+            'username',
+            'url',
+        ]
 
     def get_liker_id(self, obj):
         return obj['liker_id']

+ 28 - 8
misago/threads/serializers/thread.py

@@ -37,12 +37,30 @@ class ThreadSerializer(serializers.ModelSerializer, MutableFields):
 
     class Meta:
         model = Thread
-        fields = (
-            'id', 'category', 'title', 'replies', 'has_unapproved_posts', 'started_on',
-            'last_post_on', 'last_post_is_event', 'last_post', 'last_poster_name', 'is_unapproved',
-            'is_hidden', 'is_closed', 'weight', 'acl', 'is_new', 'is_read', 'path', 'poll',
-            'subscription', 'api', 'url',
-        )
+        fields = [
+            'id',
+            'category',
+            'title',
+            'replies',
+            'has_unapproved_posts',
+            'started_on',
+            'last_post_on',
+            'last_post_is_event',
+            'last_post',
+            'last_poster_name',
+            'is_unapproved',
+            'is_hidden',
+            'is_closed',
+            'weight',
+            'acl',
+            'is_new',
+            'is_read',
+            'path',
+            'poll',
+            'subscription',
+            'api',
+            'url',
+        ]
 
     def get_acl(self, obj):
         try:
@@ -117,7 +135,9 @@ class PrivateThreadSerializer(ThreadSerializer):
 
     class Meta:
         model = Thread
-        fields = ThreadSerializer.Meta.fields + ('participants', )
+        fields = ThreadSerializer.Meta.fields + [
+            'participants',
+        ]
 
 
 class ThreadsListSerializer(ThreadSerializer):
@@ -128,7 +148,7 @@ class ThreadsListSerializer(ThreadSerializer):
 
     class Meta:
         model = Thread
-        fields = ThreadSerializer.Meta.fields + ('has_poll', 'top_category')
+        fields = ThreadSerializer.Meta.fields + ['has_poll', 'top_category']
 
 
 ThreadsListSerializer = ThreadsListSerializer.exclude_fields('path', 'poll')

+ 1 - 1
misago/threads/serializers/threadparticipant.py

@@ -15,7 +15,7 @@ class ThreadParticipantSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = ThreadParticipant
-        fields = ('id', 'username', 'avatars', 'url', 'is_owner')
+        fields = ['id', 'username', 'avatars', 'url', 'is_owner']
 
     def get_id(self, obj):
         return obj.user.id

+ 4 - 2
misago/threads/tests/test_thread_pollvotes_api.py

@@ -23,8 +23,10 @@ class ThreadGetVotesTests(ThreadPollApiTestCase):
 
         self.api_link = reverse(
             'misago:api:thread-poll-votes',
-            kwargs={'thread_pk': self.thread.pk,
-                    'pk': self.poll.pk}
+            kwargs={
+                'thread_pk': self.thread.pk,
+                'pk': self.poll.pk,
+            }
         )
 
     def test_anonymous(self):

+ 4 - 2
misago/threads/tests/test_thread_postedits_api.py

@@ -16,8 +16,10 @@ class ThreadPostEditsApiTestCase(ThreadsApiTestCase):
 
         self.api_link = reverse(
             'misago:api:thread-post-edits',
-            kwargs={'thread_pk': self.thread.pk,
-                    'pk': self.post.pk}
+            kwargs={
+                'thread_pk': self.thread.pk,
+                'pk': self.post.pk,
+            }
         )
 
         self.override_acl()

+ 23 - 16
misago/users/djangoadmin.py

@@ -73,25 +73,32 @@ class UserAdmin(admin.ModelAdmin):
     that).
     Replaces default form with custom `UserAdminForm`.
     """
-    list_display = ('username', 'email', 'is_staff', 'is_superuser', )
-    search_fields = ('username', 'email')
-    list_filter = ('groups', 'is_staff', 'is_superuser')
+    list_display = ['username', 'email', 'is_staff', 'is_superuser']
+    search_fields = ['username', 'email']
+    list_filter = ['groups', 'is_staff', 'is_superuser']
 
     form = UserAdminForm
     actions = None
-    readonly_fields = (
-        'username', 'email', 'rank', 'last_login', 'joined_on', 'is_staff', 'is_superuser',
-    )
-    fieldsets = ((
-        _('Misago user data'), {
-            'fields': (
-                'username', 'email', 'rank', 'last_login', 'joined_on', 'is_staff', 'is_superuser',
-                'edit_from_misago_link',
-            )
-        },
-    ), (_('Edit permissions and groups'), {
-        'fields': ('groups', 'user_permissions', )
-    }, ), )
+    readonly_fields = [
+        'username', 'email', 'rank', 'last_login', 'joined_on', 'is_staff', 'is_superuser'
+    ]
+    fieldsets = [
+        [
+            _('Misago user data'),
+            {
+                'fields': (
+                    'username', 'email', 'rank', 'last_login', 'joined_on', 'is_staff',
+                    'is_superuser', 'edit_from_misago_link',
+                )
+            },
+        ],
+        [
+            _('Edit permissions and groups'),
+            {
+                'fields': ('groups', 'user_permissions', )
+            },
+        ],
+    ]
 
     def has_add_permission(self, request):
         return False

+ 19 - 7
misago/users/forms/admin.py

@@ -430,10 +430,14 @@ class BanUsersForm(forms.Form):
     ban_type = forms.MultipleChoiceField(
         label=_("Values to ban"),
         widget=forms.CheckboxSelectMultiple,
-        choices=(('usernames', _('Usernames')), ('emails', _('E-mails')),
-                 ('domains', _('E-mail domains')), ('ip', _('IP addresses')),
-                 ('ip_first', _('First segment of IP addresses')),
-                 ('ip_two', _('First two segments of IP addresses')))
+        choices=[
+            ('usernames', _('Usernames')),
+            ('emails', _('E-mails')),
+            ('domains', _('E-mail domains')),
+            ('ip', _('IP addresses')),
+            ('ip_first', _('First segment of IP addresses')),
+            ('ip_two', _('First two segments of IP addresses')),
+        ]
     )
     user_message = forms.CharField(
         label=_("User message"),
@@ -515,15 +519,23 @@ class BanForm(forms.ModelForm):
 
 
 class SearchBansForm(forms.Form):
-    SARCH_CHOICES = (('', _('All bans')), ('names', _('Usernames')), ('emails', _('E-mails')),
-                     ('ips', _('IPs')), )
+    SARCH_CHOICES = [
+        ('', _('All bans')),
+        ('names', _('Usernames')),
+        ('emails', _('E-mails')),
+        ('ips', _('IPs')),
+    ]
 
     check_type = forms.ChoiceField(label=_("Type"), required=False, choices=SARCH_CHOICES)
     value = forms.CharField(label=_("Banned value begins with"), required=False)
     state = forms.ChoiceField(
         label=_("State"),
         required=False,
-        choices=(('', _('Any')), ('used', _('Active')), ('unused', _('Expired')), )
+        choices=[
+            ('', _('Any')),
+            ('used', _('Active')),
+            ('unused', _('Expired')),
+        ]
     )
 
     def filter_queryset(self, search_criteria, queryset):

+ 5 - 1
misago/users/models/ban.py

@@ -58,7 +58,11 @@ class Ban(models.Model):
     EMAIL = 1
     IP = 2
 
-    CHOICES = ((USERNAME, _('Username')), (EMAIL, _('E-mail address')), (IP, _('IP address')), )
+    CHOICES = [
+        (USERNAME, _('Username')),
+        (EMAIL, _('E-mail address')),
+        (IP, _('IP address')),
+    ]
 
     check_type = models.PositiveIntegerField(default=USERNAME, db_index=True)
     banned_value = models.CharField(max_length=255, db_index=True)

+ 10 - 5
misago/users/models/user.py

@@ -139,16 +139,21 @@ class User(AbstractBaseUser, PermissionsMixin):
     SUBSCRIBE_NOTIFY = 1
     SUBSCRIBE_ALL = 2
 
-    SUBSCRIBE_CHOICES = ((SUBSCRIBE_NONE, _("No")), (SUBSCRIBE_NOTIFY, _("Notify")),
-                         (SUBSCRIBE_ALL, _("Notify with e-mail")))
+    SUBSCRIBE_CHOICES = [
+        (SUBSCRIBE_NONE, _("No")),
+        (SUBSCRIBE_NOTIFY, _("Notify")),
+        (SUBSCRIBE_ALL, _("Notify with e-mail")),
+    ]
 
     LIMIT_INVITES_TO_NONE = 0
     LIMIT_INVITES_TO_FOLLOWED = 1
     LIMIT_INVITES_TO_NOBODY = 2
 
-    LIMIT_INVITES_TO_CHOICES = ((LIMIT_INVITES_TO_NONE, _("Everybody")),
-                                (LIMIT_INVITES_TO_FOLLOWED, _("Users I follow")),
-                                (LIMIT_INVITES_TO_NOBODY, _("Nobody")), )
+    LIMIT_INVITES_TO_CHOICES = [
+        (LIMIT_INVITES_TO_NONE, _("Everybody")),
+        (LIMIT_INVITES_TO_FOLLOWED, _("Users I follow")),
+        (LIMIT_INVITES_TO_NOBODY, _("Nobody")),
+    ]
     """
     Note that "username" field is purely for shows.
     When searching users by their names, always use lowercased string

+ 9 - 2
misago/users/serializers/ban.py

@@ -27,7 +27,10 @@ class BanMessageSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Ban
-        fields = ('message', 'expires_on')
+        fields = [
+            'message',
+            'expires_on',
+        ]
 
     def get_message(self, obj):
         if obj.user_message:
@@ -46,7 +49,11 @@ class BanDetailsSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Ban
-        fields = ('user_message', 'staff_message', 'expires_on')
+        fields = [
+            'user_message',
+            'staff_message',
+            'expires_on',
+        ]
 
     def get_user_message(self, obj):
         return serialize_message(obj.user_message)

+ 10 - 3
misago/users/serializers/rank.py

@@ -13,10 +13,17 @@ class RankSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Rank
-        fields = (
-            'id', 'name', 'slug', 'description', 'title', 'css_class', 'is_default', 'is_tab',
+        fields = [
+            'id',
+            'name',
+            'slug',
+            'description',
+            'title',
+            'css_class',
+            'is_default',
+            'is_tab',
             'absolute_url',
-        )
+        ]
 
     def get_description(self, obj):
         if obj.description:

+ 54 - 16
misago/users/serializers/user.py

@@ -41,12 +41,30 @@ class UserSerializer(serializers.ModelSerializer, MutableFields):
 
     class Meta:
         model = UserModel
-        fields = (
-            'id', 'username', 'slug', 'email', 'joined_on', 'rank', 'title', 'avatars',
-            'is_avatar_locked', 'signature', 'is_signature_locked', 'followers', 'following',
-            'threads', 'posts', 'acl', 'is_followed', 'is_blocked', 'meta', 'status',
-            'absolute_url', 'api_url',
-        )
+        fields = [
+            'id',
+            'username',
+            'slug',
+            'email',
+            'joined_on',
+            'rank',
+            'title',
+            'avatars',
+            'is_avatar_locked',
+            'signature',
+            'is_signature_locked',
+            'followers',
+            'following',
+            'threads',
+            'posts',
+            'acl',
+            'is_followed',
+            'is_blocked',
+            'meta',
+            'status',
+            'absolute_url',
+            'api_url',
+        ]
 
     def get_acl(self, obj):
         return obj.acl
@@ -90,25 +108,45 @@ class UserSerializer(serializers.ModelSerializer, MutableFields):
     def get_api_url(self, obj):
         return {
             'root':
-                reverse('misago:api:user-detail', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-detail', kwargs={
+                    'pk': obj.pk,
+                }),
             'follow':
-                reverse('misago:api:user-follow', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-follow', kwargs={
+                    'pk': obj.pk,
+                }),
             'ban':
-                reverse('misago:api:user-ban', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-ban', kwargs={
+                    'pk': obj.pk,
+                }),
             'moderate_avatar':
-                reverse('misago:api:user-moderate-avatar', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-moderate-avatar', kwargs={
+                    'pk': obj.pk,
+                }),
             'moderate_username':
-                reverse('misago:api:user-moderate-username', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-moderate-username', kwargs={
+                    'pk': obj.pk,
+                }),
             'delete':
-                reverse('misago:api:user-delete', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-delete', kwargs={
+                    'pk': obj.pk,
+                }),
             'followers':
-                reverse('misago:api:user-followers', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-followers', kwargs={
+                    'pk': obj.pk,
+                }),
             'follows':
-                reverse('misago:api:user-follows', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-follows', kwargs={
+                    'pk': obj.pk,
+                }),
             'threads':
-                reverse('misago:api:user-threads', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-threads', kwargs={
+                    'pk': obj.pk,
+                }),
             'posts':
-                reverse('misago:api:user-posts', kwargs={'pk': obj.pk}),
+                reverse('misago:api:user-posts', kwargs={
+                    'pk': obj.pk,
+                }),
         }
 
 

+ 8 - 3
misago/users/serializers/usernamechange.py

@@ -16,7 +16,12 @@ class UsernameChangeSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = UsernameChange
-        fields = (
-            'id', 'user', 'changed_by', 'changed_by_username', 'changed_on', 'new_username',
+        fields = [
+            'id',
+            'user',
+            'changed_by',
+            'changed_by_username',
+            'changed_on',
+            'new_username',
             'old_username',
-        )
+        ]