changeset 130:5ab229c9d348

Add back ability to edit account settings * Account/profile editing is now done with a ModelForm, instead of processing the data manually. Help text and verbose names have been moved to the Profile model and to the UserForm (in the latter case, it's because we can't edit the User model directly). * The profile page now shows pygments style information and sections of the profile that are not filled are now hidden. * Some parts of apps/profiles/views.py have been rewritten (the getprofile() method has been removed, as it's no longer necessary, and the editprofile() view was rewritten in accordance with the switch to using ModelForms). * The styling for forms has been modified slightly.
author dellsystem <ilostwaldo@gmail.com>
date Sat, 22 Sep 2012 11:18:23 -0400
parents be8fec1e85d9
children d6f65888e0f3
files apps/profile/forms.py apps/profile/models.py apps/profile/urls.py apps/profile/views.py static/css/agora.less static/css/variables.less templates/field.djhtml templates/profile/edit-user.djhtml templates/profile/user.djhtml
diffstat 9 files changed, 145 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/profile/forms.py	Sat Sep 22 11:18:23 2012 -0400
@@ -0,0 +1,25 @@
+from django.forms import ModelForm
+from django.contrib.auth.models import User
+from django.utils.translation import ugettext as _
+
+from agora.apps.profile.models import Profile
+
+
+class ProfileForm(ModelForm):
+    class Meta:
+        model = Profile
+        exclude = ('user',)
+
+
+class UserForm(ModelForm):
+    class Meta:
+        model = User
+        fields = ('first_name', 'last_name')
+
+    def __init__(self, *args, **kwargs):
+        super(UserForm, self).__init__(*args, **kwargs)
+
+        # Change the help text for names
+        name_text = _("We will display your name according to most Western \
+        European conventions, your given name(s) followed by your surname(s).")
+        self.fields['first_name'].help_text = name_text
--- a/apps/profile/models.py	Sat Sep 22 11:12:30 2012 -0400
+++ b/apps/profile/models.py	Sat Sep 22 11:18:23 2012 -0400
@@ -1,5 +1,6 @@
 from django.db import models
 from django.contrib.auth.models import User
+from django.utils.translation import ugettext as _
 
 from agora.apps.free_license.models import FreeLicense
 from agora.apps.pygments_style.models import PygmentsStyle
@@ -7,10 +8,23 @@
 
 class Profile(models.Model):
     user = models.OneToOneField(User)
-    preferred_license = models.ForeignKey(FreeLicense, default=1)
-    interests = models.CharField(max_length=512, null=True, blank=True)
-    blurb = models.TextField(max_length=16384, null=True, blank=True)
-    pygments_style = models.ForeignKey(PygmentsStyle, default=1)
+    preferred_license = models.ForeignKey(FreeLicense, help_text=_("\
+        By default, all of your submissions will be under the following \
+        license, and this license will be displayed next to your \
+        submissions. <a href=\"/licenses/\">Find out more.</a>"),
+        default=1)
+    interests = models.CharField(max_length=512, null=True, help_text=_("\
+        Tell us about your research interests (e.g. \
+        <em>signal processing</em>, <em>hyperbolic PDEs</em>). These \
+        keywords will be used when searching for submissions."), blank=True,
+        verbose_name=_("Research interests"))
+    blurb = models.TextField(max_length=16384, null=True, help_text=_("\
+        Finally, anything else you would like to say about yourself."),
+        blank=True)
+    pygments_style = models.ForeignKey(PygmentsStyle, default=1,
+        verbose_name=_('Syntax highlighting style'), help_text=_("\
+        Choose a stylesheet for displayed syntax-highlighted code. Most of \
+        these stylesheets are based off of default Pygments stylesheets."))
 
     def __unicode__(self):
         return self.user.username
--- a/apps/profile/urls.py	Sat Sep 22 11:12:30 2012 -0400
+++ b/apps/profile/urls.py	Sat Sep 22 11:18:23 2012 -0400
@@ -2,5 +2,5 @@
 
 urlpatterns = patterns('agora.apps.profile.views',
     url(r'^editprofile$', 'editprofile', name='edit_profile'),
-    url(r'^(?P<user>\w*)/$', 'showprofile', name='show_profile'),
+    url(r'^(?P<username>\w*)/$', 'showprofile', name='show_profile'),
 )
--- a/apps/profile/views.py	Sat Sep 22 11:12:30 2012 -0400
+++ b/apps/profile/views.py	Sat Sep 22 11:18:23 2012 -0400
@@ -1,81 +1,57 @@
-from django.shortcuts import render_to_response, get_object_or_404
+from django.shortcuts import render, get_object_or_404, redirect
 from django.contrib.auth.models import User
-from django.http import Http404, HttpResponseRedirect
-from django.core.urlresolvers import reverse
 from django.contrib.auth.decorators import login_required
-from django.views.generic.simple import direct_to_template
 
 from agora.apps.free_license.models import FreeLicense
 from agora.apps.bundle.models import Bundle
 from agora.apps.snippet.models import Snippet
 from agora.apps.profile.models import Profile
-from agora.middleware.http import Http403
+from agora.apps.profile.forms import UserForm, ProfileForm
 
 
-def getprofile(user):
-    u = get_object_or_404(User, username=user)
-
-    #Inactive users "don't exist"
-    if not u.is_active:
-        raise Http404
+def showprofile(request, username):
+    user = get_object_or_404(User, username=username)
+    profile = user.get_profile()
 
-    #Get profile or create a default if none exists
-    try:
-        p = u.get_profile()
-    except Profile.DoesNotExist:
-        #At least one FreeLicense *must* exist.
-        p = Profile(user=u, preferred_license=FreeLicense.objects.get(id=1))
-        p.save()
-
-    return [u,p]
+    if user.first_name or user.last_name:
+        name = user.get_full_name()
+    else:
+        name = user.username
 
-def showprofile(request, user):
-    [u,p] = getprofile(user)
-
-    if u.first_name or u.last_name:
-        n = u.get_full_name()
-    else:
-        n = u.username
+    b = Bundle.objects.filter(uploader=user)
+    s = Snippet.objects.filter(author=user)
 
-    b = Bundle.objects.filter(uploader=u)
-    s = Snippet.objects.filter(author=u)
+    context = {
+        'profile': user.get_profile,
+        'name': name,
+        'bundles': Bundle.objects.filter(uploader=user),
+        'snippets': Snippet.objects.filter(author=user),
+    }
 
-    return direct_to_template(request, 'profile/user.djhtml',
-                              {
-                                  'profile' : p,
-                                  'bundles' : b,
-                                  'snippets' : s,
-                                  'name' : n,
-                               },
-                              )
+    return render(request, 'profile/user.djhtml', context)
+
 
 @login_required
 def editprofile(request):
-    [u,p] = getprofile(request.user)
+    user = request.user
+    profile = user.get_profile()
 
-    if request.method=='POST':
-        u.first_name = request.POST['first-name']
-        u.last_name  = request.POST['last-name']
-        u.save()
-
-        try:
-            p.preferred_license = \
-                            FreeLicense.objects.get(id=request.POST['license'])
-        except:
-            p.preferred_license = FreeLicense.objects.get(id=1)
+    if request.method == 'POST':
+        user_form = UserForm(request.POST, instance=user)
+        profile_form = ProfileForm(request.POST, instance=profile)
 
-        p.interests = request.POST['interests']
-        p.blurb = request.POST['blurb']
-        p.save()
-        return HttpResponseRedirect(reverse(
-                                    'agora.apps.profile.views.showprofile',
-                                    args=(u,))
-                                    )
+        if user_form.is_valid() and profile_form.is_valid():
+            user_form.save()
+            profile_form.save()
+            return redirect(user)
+    else:
+        user_form = UserForm(instance=user)
+        profile_form = ProfileForm(instance=profile)
 
-    licenses = FreeLicense.objects.all()
-    return direct_to_template(request, 'profile/edit-user.djhtml',
-                              {
-                                  'profile' : p,
-                                  'licenses' : licenses,
-                              },
-                              )
+    context = {
+        'profile': profile,
+        'user_form': user_form,
+        'profile_form': profile_form,
+    }
+
+    return render(request, 'profile/edit-user.djhtml', context)
--- a/static/css/agora.less	Sat Sep 22 11:12:30 2012 -0400
+++ b/static/css/agora.less	Sat Sep 22 11:18:23 2012 -0400
@@ -313,11 +313,27 @@
         label {
             float: left;
             text-align: right;
+            padding-right: 20px;
+            padding-top: 10px;
+            font-weight: bold;
+            width: 180px;
         }
     }
 
     .form-input {
-        margin-left: 180px;
+        margin-left: 200px;
+        padding: 5px 0;
+        input[type=text] {
+            width: @fieldWidth;
+            height: 20px;
+        }
+        textarea {
+            width: @fieldWidth;
+        }
+        p {
+            padding-top: 10px;
+            padding-bottom: 0;
+        }
     }
 
     .errors {
--- a/static/css/variables.less	Sat Sep 22 11:12:30 2012 -0400
+++ b/static/css/variables.less	Sat Sep 22 11:18:23 2012 -0400
@@ -28,3 +28,4 @@
 @nonSidebarWidth:   @fixedWidth - @sidebarWidth - @sidebarLeftSpace;
 @inputPadding:      5px;
 @sidebarPadding:    10px;
+@fieldWidth:        400px;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/field.djhtml	Sat Sep 22 11:18:23 2012 -0400
@@ -0,0 +1,15 @@
+{% if field.errors %}
+<div class="errors">
+    {{ field.errors }}
+</div>
+{% endif %}
+
+<div class="form-line">
+    {{ field.label_tag }}
+    <div class="form-input">
+        {{ field }}
+        {% if field.help_text %}
+        <p>{{ field.help_text|safe }}</p>
+        {% endif %}
+    </div>
+</div>
--- a/templates/profile/edit-user.djhtml	Sat Sep 22 11:12:30 2012 -0400
+++ b/templates/profile/edit-user.djhtml	Sat Sep 22 11:18:23 2012 -0400
@@ -1,76 +1,34 @@
-{% extends "profile/user.djhtml" %}
+{% extends "base.djhtml" %}
 
-{% block boxtitle %}
-Edit your profile
-{% endblock boxtitle %}
+{% block breadcrubs %}
+Viewing your profile
+{% endblock %}
 
-{% block boxcontents %}
-<p class="explanation">
+{% block content %}
+<h1>Edit your account settings ({{ user }})</h1>
+<p class="hint">
 You can provide some extra optional information about yourself. We
 recommend that you provide us with a real name. If you do, it will be
 displayed next to all of your contributions instead of your Agora
 username.
 </p>
-<form id="userinfo" method="post" action=".">
-
-  {% csrf_token %}
+<form method="post">
+    {% if form.non_field_errors %}
+    {{ form.non_field_errors }}
+    {% endif %}
+    {% csrf_token %}
 
-  <p class="explanation">
-    We will display your name according to most Western European
-    conventions, your given name(s) followed by your surname(s).
-  </p>
-  <span class="userfield">Given name(s)</span>
-  <input type="text"
-         name="first-name"
-         id="edit-first-name"
-         value="{{user.first_name}}" /> <br />
-  <span class="userfield">Surname(s)</span>
-  <input type="text"
-         id="edit-last-name"
-         name="last-name"
-         value="{{user.last_name}}" /> <br />
-
-  <p class="explanation">
-    By default, all of your submissions will be under the following
-    license, and will be displayed next to your submissions.
-    <a href="{% url agora.apps.free_license.views.index %}">
-      Here is a thorough explanation of the available licenses.
-    </a>
-  </p>
+    {% for field in user_form %}
+    {% include "field.djhtml" %}
+    {% endfor %}
 
-  <span class="userfield">Preferred license</span>
-  <select name="license" id="edit-license">
-  {% for license in licenses %}
-  <option value="{{ license.id }}"
-          {% if license = profile.preferred_license %}
-          selected="true"
-          {% endif %}
-          />
-  {{license.name}}
-  </option>
-  {% endfor %}
-  </select>
+    {% for field in profile_form %}
+    {% include "field.djhtml" %}
+    {% endfor %}
 
-  <p class="explanation">
-    Tell us about your research interests (e.g. <em>signal processing</em>,
-    <em>hyperbolic PDEs</em>). These keywords will be used when
-    searching for submissions.
-  </p>
-  <span class="userfield">Research interests</span>
-  <input type="text"
-         name="interests"
-         id="edit-interests"
-         value="{{profile.interests}}" /> <br />
-
-  <p class="explanation">
-    Finally, anything else you would like to say about yourself.
-  </p>
-
-  <span class="userfield">Blurb</span>
-
-  <textarea name="blurb" id="edit-blurb">{{profile.blurb}}</textarea>
-  <br/>
-
-  <input type="submit" value="Update profile" />
+    <div class="center-align">
+        <button type="submit" class="button large">Submit</button>
+        <button type="reset" class="button large">Reset</button>
+    </div>
 </form>
-{% endblock boxcontents %}
+{% endblock %}
--- a/templates/profile/user.djhtml	Sat Sep 22 11:12:30 2012 -0400
+++ b/templates/profile/user.djhtml	Sat Sep 22 11:18:23 2012 -0400
@@ -17,15 +17,22 @@
 
     <dt>Preferred license:</dt>
     <dd>{{ profile.preferred_license }}</dd>
+
+    <dt>Syntax highlighting style:</dt>
+    <dd>{{ profile.pygments_style }}</dd>
 </dl>
 
+{% if profile.interests %}
 <h2>Interests</h2>
 
 <p>{{ profile.interests }}</p>
+{% endif %}
 
+{% if profile.blurb %}
 <h2>About {{ name }}</h2>
 
 <p>{{ profile.blurb }}</p>
+{% endif %}
 {% endblock %}
 
 {% block content-related %}