Repository: CiviWiki/OpenCiviWiki

Issue:
Refactor function-based view to class-based
### Idea summary

Rewrite function-based view to class-based and add docstring

### Further details

In the accounts app's view, there is a function-based view called user_profile: 
```python
@login_required
@full_profile
def user_profile(request, username=None):
    if request.method == "GET":
        if not username:
            return HttpResponseRedirect(f"/profile/{request.user}")
        else:
            is_owner = username == request.user.username
            try:
                user = get_user_model().objects.get(username=username)
            except get_user_model().DoesNotExist:
                return HttpResponseRedirect("/404")

        form = ProfileEditForm(
            initial={
                "username": user.username,
                "email": user.email,
                "first_name": user.profile.first_name or None,
                "last_name": user.profile.last_name or None,
                "about_me": user.profile.about_me or None,
            },
            readonly=True,
        )
        data = {
            "username": user,
            "profile_image_form": UpdateProfileImage,
            "form": form if is_owner else None,
            "readonly": True,
        }
        return TemplateResponse(request, "account.html", data)
```
All views in this file are created using classes, so I think it will be great to rewrite this view for better sticking to the code style. Moreover, this view has no docstring. I'm new to contributing to Open Source. I want to solve this issue, and I know-how.  


Discussion:
I started some coding and am almost done. I have noticed that @login_required and @full_profile decorators are only used in this view. The first decorator can be replaced by mixin and the second by adding approximately three lines of code in the view. I don't think that there is any need to create custom decorators for such purposes

Resolving patch:
diff --git a/project/accounts/urls/urls.py b/project/accounts/urls/urls.py
--- a/project/accounts/urls/urls.py
+++ b/project/accounts/urls/urls.py
@@ -9,7 +9,7 @@
     PasswordResetConfirmView,
     PasswordResetCompleteView,
     ProfileSetupView,
-    user_profile,
+    UserProfileView,
 )
 
 urlpatterns = [
@@ -22,7 +22,7 @@
     path("register/", RegisterView.as_view(), name="accounts_register"),
     path("settings/", SettingsView.as_view(), name="accounts_settings"),
     path("setup/", ProfileSetupView.as_view(), name="accounts_profile_setup"),
-    path("profile/<str:username>/", user_profile, name="profile"),
+    path("profile/<str:username>/", UserProfileView.as_view(), name="profile"),
     path(
         "activate_account/<uidb64>/<token>/",
         ProfileActivationView.as_view(),
diff --git a/project/accounts/views.py b/project/accounts/views.py
--- a/project/accounts/views.py
+++ b/project/accounts/views.py
@@ -4,7 +4,7 @@
 This module will include views for the accounts app.
 """
 
-from core.custom_decorators import full_profile, login_required
+from core.custom_decorators import full_profile
 from django.conf import settings
 from django.contrib.auth import get_user_model, login
 from django.contrib.auth import views as auth_views
@@ -15,6 +15,7 @@
 from django.urls import reverse_lazy
 from django.utils.encoding import force_str
 from django.utils.http import urlsafe_base64_decode
+from django.utils.decorators import method_decorator
 from django.views import View
 from django.views.generic.edit import FormView, UpdateView
 
@@ -165,16 +166,18 @@ def get(self, request):
             return TemplateResponse(request, "accounts/user-setup.html", data)
 
 
-@login_required
-@full_profile
-def user_profile(request, username=None):
-    if request.method == "GET":
+class UserProfileView(LoginRequiredMixin, View):
+    """A view that shows profile for authorized users"""
+
+    @method_decorator(full_profile)
+    def get(self, request, username=None):
         if not username:
             return HttpResponseRedirect(f"/profile/{request.user}")
         else:
             is_owner = username == request.user.username
             try:
                 user = get_user_model().objects.get(username=username)
+
             except get_user_model().DoesNotExist:
                 return HttpResponseRedirect("/404")
 


Test patch: