Mercurial > hg > agora
changeset 35:290dd9208cc4
Implement editing user profiles and fix bugs related to the login/logout buttons. Implement 403 exception
author | Jordi Gutiérrez Hermoso <jordigh@gmail.com> |
---|---|
date | Mon, 05 Jul 2010 00:31:20 -0500 |
parents | 22d514498935 |
children | bc0137b6c264 |
files | apps/bundle/views.py apps/profile/views.py middleware/__init__.py middleware/http.py settings.py templates/403.html templates/base.djhtml templates/profile/edit-user.djhtml templates/profile/user.djhtml templates/user.djhtml urls.py |
diffstat | 10 files changed, 217 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/apps/bundle/views.py +++ b/apps/bundle/views.py @@ -1,9 +1,15 @@ from django.shortcuts import render_to_response, get_object_or_404 from agora.apps.bundle.models import * +from django.template import RequestContext def detail(request, user, bundle): b = get_object_or_404(Bundle, uploader__username=user, name=bundle) f = BundleFile.objects.filter(bundle=b) - return render_to_response('bundle/index.djhtml', {'bundle':b, - 'files': f,}) + return render_to_response('bundle/index.djhtml', + { + 'bundle':b, + 'files': f, + }, + RequestContext(request), + )
--- a/apps/profile/views.py +++ b/apps/profile/views.py @@ -1,37 +1,87 @@ from django.shortcuts import render_to_response, get_object_or_404 -from agora.apps.profile.models import Profile from django.contrib.auth.models import User -from django.http import Http404 +from django.http import Http404, HttpResponseRedirect +from django.core.urlresolvers import reverse +from django.contrib.auth.decorators import login_required +from django.template import RequestContext + 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 -def showprofile(request, user): +from agora.middleware.http import Http403 + +def getprofile(user): u = get_object_or_404(User, username=user) #Inactive users "don't exist" if not u.is_active: raise Http404 + #Get profile or create a default if none exists try: p = u.get_profile() - #Create a default profile if none exists 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] + +def showprofile(request, user): + [u,p] = getprofile(user) + if u.first_name or u.last_name: - n = u.first_name + " " + u.last_name + n = u.get_full_name() else: n = u.username b = Bundle.objects.filter(uploader=u) s = Snippet.objects.filter(uploader=u) - return render_to_response('user.djhtml', {'user' : u, - 'profile' : p, - 'bundles' : b, - 'snippets' : s, - 'name' : n, - }) + return render_to_response('profile/user.djhtml', + { + 'profile' : p, + 'bundles' : b, + 'snippets' : s, + 'name' : n, + }, + RequestContext(request) + ) + +@login_required +def editprofile(request, user): + [u,p] = getprofile(user) + + #Make sure user can only edit own profile + if request.user != u: + raise Http403 + + 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) + + p.interests = request.POST['interests'] + p.blurb = request.POST['blurb'] + p.save() + return HttpResponseRedirect(reverse( + 'agora.apps.profile.views.showprofile', + args=(u,)) + ) + + licenses = FreeLicense.objects.all() + return render_to_response('profile/edit-user.djhtml', + { + 'profile' : p, + 'licenses' : licenses, + }, + RequestContext(request) + )
new file mode 100644 --- /dev/null +++ b/middleware/http.py @@ -0,0 +1,30 @@ +from django.template import RequestContext +from django.conf import settings +from django.core.exceptions import PermissionDenied +from django.http import HttpResponseForbidden +from django.template import loader + +class Http403(Exception): + pass + +def render_to_403(*args, **kwargs): + """ + Returns a HttpResponseForbidden whose content is filled with + the result of calling + django.template.loader.render_to_string() with the passed + arguments. + """ + if not isinstance(args,list): + args = [] + args.append('403.html') + + httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)} + response = HttpResponseForbidden(loader.render_to_string(*args, **kwargs), + **httpresponse_kwargs) + + return response + +class Http403Middleware(object): + def process_exception(self,request,exception): + if isinstance(exception,Http403): + return render_to_403(context_instance=RequestContext(request))
--- a/settings.py +++ b/settings.py @@ -97,11 +97,14 @@ ) MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + + #Agora-specific middleware + 'agora.middleware.http.Http403Middleware', ) ROOT_URLCONF = 'agora.urls'
new file mode 100644 --- /dev/null +++ b/templates/403.html @@ -0,0 +1,16 @@ +{% extends "whitebox.djhtml" %} + +{% block title %} +Access denied +{% endblock %} + +{% block boxtitle %} +Access denied +{% endblock %} + +{% block boxcontents %} +<p> + You requested access to a portion of Agora for which you don't have + permission. If you believe this is a mistake, please let us know. +</p> +{% endblock %}
--- a/templates/base.djhtml +++ b/templates/base.djhtml @@ -7,7 +7,7 @@ <title>Agora Octave — {% block title %} - Free your math! + Free your numbers! {% endblock %} </title>
new file mode 100644 --- /dev/null +++ b/templates/profile/edit-user.djhtml @@ -0,0 +1,76 @@ +{% extends "profile/user.djhtml" %} + +{% block boxtitle %} +Edit your profile +{% endblock boxtitle %} + +{% block boxcontents %} +<p class="explanation"> +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 %} + + <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="/licenses"> + Here is a thorough explanation of the available licenses. + </a> + </p> + + <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> + + <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" /> +</form> +{% endblock boxcontents %}
rename from templates/user.djhtml rename to templates/profile/user.djhtml --- a/templates/user.djhtml +++ b/templates/profile/user.djhtml @@ -1,10 +1,19 @@ {% extends "whitebox.djhtml" %} + {% block boxtitle %} -{{user.username}} -{% endblock %} +{{profile.user.username}} <br/> +{% if profile.user = user %} +<small> + (<a href="{% url agora.apps.profile.views.editprofile user %}"> + edit profile + </a>) +</small> +{% endif %} +{% endblock boxtitle%} + {% block boxcontents %} <div id="userinfo"> - {% if user.first_name or user.last_name %} + {% if profile.user.first_name or profile.user.last_name %} <span class="userfield">Name</span> <span class="userdata">{{name}}</span> <br /> @@ -30,7 +39,7 @@ </p> </div> {% endif %} -{% endblock %} {# boxcontents #} +{% endblock boxcontents %} {% block content-related %} {% if bundles or snippets %} @@ -45,7 +54,7 @@ </h5> <ul> {% for b in bundles %} - <li> <a href="/{{user.username}}/{{b.name}}">{{b.name}} </a></li> + <li> <a href="/{{profile.user.username}}/{{b.name}}">{{b.name}} </a></li> {% endfor %} </ul> {% endif %} @@ -62,4 +71,4 @@ </div> </div> {% endif %} -{% endblock %} {# content-related #} +{% endblock content-related %}
--- a/urls.py +++ b/urls.py @@ -18,7 +18,8 @@ (r'^accounts/', include('registration.urls')), - (r'^(?P<user>[\w|_]*)/$', 'agora.apps.profile.views.showprofile'), + (r'^editprofile/(?P<user>\w*)/$', 'agora.apps.profile.views.editprofile'), + (r'^(?P<user>\w*)/$', 'agora.apps.profile.views.showprofile'), (r'^', include('agora.apps.bundle.urls')),