Repository: CiviWiki/OpenCiviWiki

Issue:
Create user profile template
When migrating the old frontend templates to Django, we noticed the user profile was not rendering any content. Rather than weed through the proclaimed "horrendous code" that was responsible for rendering the BackBone view, let's just write a _simple_ user profile template from scratch. 

https://github.com/CiviWiki/OpenCiviWiki/blob/374381b6e4b9b556580157f33fbd8c67204c1b36/project/webapp/static/js/account.js#L32-L33

## Task
- determine what fields are available on the user profile
- sketch a basic user profile page using pencil and paper or a drawing app
- discuss the proposed sketch
- implement the sketch using conventional Django elements like Form and class-based views


Discussion:
[Here](https://github.com/CiviWiki/OpenCiviWiki/blob/develop/project/accounts/models.py#L5-L11), I couldn't find any fields specified in the User model. Is there some other model, defined elsewhere?
We have an `Account` model that is basically the equivalent of a user profile:

https://github.com/CiviWiki/OpenCiviWiki/blob/374381b6e4b9b556580157f33fbd8c67204c1b36/project/api/models/account.py#L105

I propose we 
1. move the `Account` model source code into the `accounts` app
2. rename the `Account` model to `Profile`
3. create a FormView for the `Profile` model with route
4. change front-end links to use the new 'ProfileForm` view/route
I opened an issue to move all accounts related code to the accounts app and rename the `Account` model to `Profile`: #926 
This task can focus on rendering the profile edit form and should be considered a child task of #926
@brylie  I worked on settings forms issue and this looks similar to that so could you assign it to  me?
secondly should we also have a PR  template  ?  I can create one if you could create a ticket for it an assign it to me

@wassafshahzad thanks for the help :-) I've assigned you to the issue.
> @wassafshahzad thanks for the help :-) I've assigned you to the issue.

No problem always happy to help
@brylie would you kindly explain how will this be different from the settings form?
I could make it so that this form is readonly and clicking an edit button will redirect you to settings form.
@wassafshahzad good point. Let's perhaps deprecate the "user profile" form/template in favor of the settings page. I.e. just link directly to the settings page and remove any code/mention of "profile" perhaps?
So should i change the link from profileView to settingView ?
if possible could you explain your idea ? 
Thank you
@wassafshahzad yes. Linking to `settingView` is fine for now.

Resolving patch:
diff --git a/project/accounts/api.py b/project/accounts/api.py
--- a/project/accounts/api.py
+++ b/project/accounts/api.py
@@ -3,7 +3,7 @@
 from rest_framework.decorators import action
 from rest_framework.response import Response
 from api.permissions import IsAccountOwnerOrDuringRegistrationOrReadOnly
-
+from api.utils import get_account
 from api.models import Thread
 from accounts.models import Account
 from api.serializers import (
diff --git a/project/accounts/forms.py b/project/accounts/forms.py
--- a/project/accounts/forms.py
+++ b/project/accounts/forms.py
@@ -215,6 +215,16 @@ class UpdateAccount(forms.ModelForm):
     Form for updating Account data
     """
 
+    def __init__(self, *args, **kwargs):
+        readonly = kwargs.pop("readonly", False)
+        super(UpdateAccount, self).__init__(*args, **kwargs)
+        if readonly:
+            self.disable_fields()
+
+    def disable_fields(self):
+        for _, field in self.fields.items():
+            field.disabled = True
+
     class Meta:
         model = Account
         fields = [
@@ -332,4 +342,3 @@ def clean_profile_image(self):
             pass
 
         return profile_image
-
diff --git a/project/frontend_views/views.py b/project/frontend_views/views.py
--- a/project/frontend_views/views.py
+++ b/project/frontend_views/views.py
@@ -11,11 +11,13 @@
 
 from api.models import Category, Thread, Civi, Activity
 from accounts.models import Account
+from accounts.forms import UpdateAccount
 from api.forms import UpdateProfileImage
 from core.constants import US_STATES
 from core.custom_decorators import login_required, full_account
 
 from django.contrib.auth import get_user_model
+
 User = get_user_model()
 
 
@@ -64,18 +66,34 @@ def base_view(request):
 @login_required
 @full_account
 def user_profile(request, username=None):
-    if not username:
-        return HttpResponseRedirect("/profile/{0}".format(request.user))
-    else:
-        try:
-            user = User.objects.get(username=username)
-        except User.DoesNotExist:
-            return HttpResponseRedirect("/404")
-    data = {
-        "username": user,
-        "profile_image_form": UpdateProfileImage,
-    }
-    return TemplateResponse(request, "account.html", data)
+    if request.method == "GET":
+        if not username:
+            return HttpResponseRedirect("/profile/{0}".format(request.user))
+        else:
+            is_owner = username == request.user.username
+            try:
+                user = User.objects.get(username=username)
+                account = user.account_set.first()
+            except User.DoesNotExist:
+                return HttpResponseRedirect("/404")
+
+        form = UpdateAccount(
+            initial={
+                "username": user.username,
+                "email": user.email,
+                "first_name": account.first_name or None,
+                "last_name": account.last_name or None,
+                "about_me": account.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)
 
 
 @login_required
@@ -123,9 +141,7 @@ def issue_thread(request, thread_id=None):
         },
         "contributors": [
             Account.objects.chip_summarize(a)
-            for a in Account.objects.filter(
-                pk__in=c_qs.values("author").distinct()
-            )
+            for a in Account.objects.filter(pk__in=c_qs.values("author").distinct())
         ],
         "category": {"id": t.category.id, "name": t.category.name},
         "categories": [{"id": c.id, "name": c.name} for c in Category.objects.all()],


Test patch: