Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote-tracking branch 'fhahn/class-based-views' into class-bas…

…ed-views
  • Loading branch information...
commit a17de12828d43043b0db850d43a033e264823e97 2 parents 24f9221 + 4ffbd3d
@brutasse authored
View
BIN  djangopeople/fixtures/pony.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
10 djangopeople/forms.py
@@ -15,6 +15,10 @@
from djangopeople.models import (DjangoPerson, Country, Region, User,
RESERVED_USERNAMES)
+from cStringIO import StringIO
+from PIL import Image
+import hashlib
+import os
def region_choices():
# For use with GroupedChoiceField
@@ -205,8 +209,10 @@ def clean_region(self):
clean_location_description = not_in_the_atlantic
-class PhotoUploadForm(forms.Form):
- photo = forms.ImageField()
+class PhotoUploadForm(forms.ModelForm):
+ class Meta:
+ model = DjangoPerson
+ fields = ('photo',)
class SkillsForm(forms.ModelForm):
View
7 djangopeople/models.py
@@ -6,6 +6,11 @@
from geopy import distance
from django.utils.safestring import mark_safe
from django.utils.html import escape
+from storages.backends.hashpath import HashPathStorage
+
+
+fs = HashPathStorage()
+
import tagging
RESERVED_USERNAMES = set((
@@ -105,7 +110,7 @@ class DjangoPerson(models.Model):
location_description = models.CharField(max_length=50)
# Profile photo
- photo = models.ImageField(blank=True, upload_to='profiles')
+ photo = models.ImageField(blank=True, upload_to='profiles', storage=fs)
# Stats
profile_views = models.IntegerField(default=0)
View
46 djangopeople/templates/upload_profile_photo.html
@@ -1,22 +1,24 @@
-{% extends "profile.html" %}
-
-{% block title%}Upload a profile photo |{% endblock %}
-
-{% block js %}{% endblock %}
-{% block map %}{% endblock %}
-
- {% block content %}
- <div class="primary">
- <h2>{% if person.photo %}Upload a new profile photo{% else %}Add a profile photo{% endif %}</h2>
- <form enctype="multipart/form-data" method="post" action=".">{% csrf_token %}
- <div class="fieldWrapper">
- {{ form.photo.errors }}
- <label for="id_photo">Photo</label>
- {{ form.photo }}
- </div>
- <p class="help">Photos will be resized and cropped to a 83x83 square; for the best results, make sure you are uploading a square image.</p>
- <p><input type="submit" value="Upload"></p>
- </form>
-
- </div>
- {% endblock %}
+{% extends "base.html" %}
+{% load url from future %}
+
+{% block title %}Upload a profile photo |{% endblock %}
+
+{% block nav_li_class_account %} class="current"{% endblock %}
+
+{% block js %}
+{% endblock %}
+
+{% block header%}
+<h2>{% if person.photo %}Upload a new profile photo{% else %}Add a profile photo{% endif %}</h2>
+{% endblock %}
+
+{% block content %}
+
+ <form enctype="multipart/form-data" method="post" action="{% url 'upload_profile_photo' user.username %}">
+
+ {% include 'includes/form.html' %}
+
+ <p class="help">Photos will be resized and cropped to a 83x83 square; for the best results, make sure you are uploading a square image.</p>
+ <div class="buttonContainer"><input type="submit" value="Upload"></div>
+ </form>
+{% endblock %}
View
115 djangopeople/tests/edit_views.py
@@ -1,13 +1,18 @@
+import os
+import shutil
+import hashlib
+
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.test import TestCase
+from django.conf import settings
from tagging.utils import edit_string_for_tags
-from djangopeople.models import DjangoPerson, Country
-
from machinetags.utils import tagdict
+from djangopeople.models import DjangoPerson, Country
+
class EditViewTest(TestCase):
fixtures = ['test_data']
@@ -16,6 +21,24 @@ def setUp(self):
super(EditViewTest, self).setUp()
self.client.login(username='daveb', password='123456')
+ img_content = open(os.path.join(settings.OUR_ROOT,
+ 'djangopeople/fixtures/pony.gif'),
+ 'rb').read()
+ sha1sum = hashlib.sha1(img_content).hexdigest()
+ self.hashed_upload_img_file_name = os.path.join(sha1sum[:1],
+ sha1sum[1:2], sha1sum)
+
+
+ # make sure the profile upload folder exists
+ self.profile_img_path = os.path.join(settings.MEDIA_ROOT, 'profiles')
+ if not os.path.exists(self.profile_img_path):
+ os.makedirs(self.profile_img_path)
+
+ def tearDown(self):
+ # remove uploaded profile picture
+ if os.path.exists(self.profile_img_path):
+ shutil.rmtree(self.profile_img_path)
+
def test_edit_finding_permissions(self):
'''
logged in user can only edit his own skills
@@ -792,3 +815,91 @@ def test_edit_location_not_in_the_atlantic(self):
self.assertFormError(response, 'form', 'location_description',
('Drag and zoom the map until the crosshair '
'matches your location'))
+
+ def test_upload_profile_photo_form_error_empty_file(self):
+ upload_file_path = '/dev/null'
+ url_upload_profile_photo = reverse('upload_profile_photo',
+ args=['daveb'])
+ # upload an empty file
+ response = self.client.post(url_upload_profile_photo,
+ {'photo': open(upload_file_path)})
+
+ self.assertFormError(response, 'form', 'photo', 'The submitted file '
+ 'is empty.')
+
+ def test_upload_profile_photo_form_error_invalid_image(self):
+ upload_file_path = os.path.join(settings.OUR_ROOT,
+ 'djangopeople/fixtures/test_data.json')
+ url_upload_profile_photo = reverse('upload_profile_photo',
+ args=['daveb'])
+ # upload an invalid file
+ response = self.client.post(url_upload_profile_photo,
+ {'photo': open(upload_file_path)})
+
+ self.assertFormError(response, 'form', 'photo', 'Upload a valid image.'
+ ' The file you uploaded was either not an image '
+ 'or a corrupted image.')
+
+ def test_upload_profile_photo(self):
+ # test to add a profile photo
+ upload_file_path = os.path.join(settings.OUR_ROOT,
+ 'djangopeople/fixtures/pony.gif')
+ url_upload_profile_photo = reverse('upload_profile_photo',
+ args=['daveb'])
+ response = self.client.get(url_upload_profile_photo)
+ self.assertContains(response, '<h2>Add a profile photo</h2>')
+
+ # upload a photo
+ response = self.client.post(url_upload_profile_photo,
+ {'photo': open(upload_file_path)})
+
+ self.assertEquals(response.status_code, 302)
+ self.assertEquals('http://testserver'+reverse('upload_done',
+ args=['daveb']),
+ response._headers['location'][1])
+
+ p = DjangoPerson.objects.get(user__username='daveb')
+ image_path = os.path.join(settings.MEDIA_ROOT, 'profiles',
+ self.hashed_upload_img_file_name)
+ self.assertEqual(p.photo.path, image_path)
+ self.assertTrue(os.path.exists(image_path))
+
+ def test_upload_profile_photo_same_file(self):
+ """
+ A user uploads the same file twice
+ """
+
+ # test to add a profile photo
+ upload_file_path = os.path.join(settings.OUR_ROOT,
+ 'djangopeople/fixtures/pony.gif')
+ url_upload_profile_photo = reverse('upload_profile_photo', args=['daveb'])
+ response = self.client.get(url_upload_profile_photo)
+ self.assertContains(response, '<h2>Add a profile photo</h2>')
+
+ # upload a photo
+ response = self.client.post(url_upload_profile_photo,
+ {'photo': open(upload_file_path)})
+
+ self.assertEquals(response.status_code, 302)
+ self.assertEquals('http://testserver'+reverse('upload_done', args=['daveb']),
+ response._headers['location'][1])
+
+ p = DjangoPerson.objects.get(user__username='daveb')
+ image_path = os.path.join(settings.MEDIA_ROOT, 'profiles',
+ self.hashed_upload_img_file_name)
+ self.assertEqual(p.photo.path, image_path)
+ self.assertTrue(os.path.exists(image_path))
+
+ # upload a same photo again
+ response = self.client.post(url_upload_profile_photo,
+ {'photo': open(upload_file_path)})
+
+ self.assertEquals(response.status_code, 302)
+ self.assertEquals('http://testserver'+reverse('upload_done', args=['daveb']),
+ response._headers['location'][1])
+
+ p = DjangoPerson.objects.get(user__username='daveb')
+ image_path = os.path.join(settings.MEDIA_ROOT, 'profiles',
+ self.hashed_upload_img_file_name)
+ self.assertEqual(p.photo.path, image_path)
+ self.assertTrue(os.path.exists(image_path))
View
57 djangopeople/views.py
@@ -1,15 +1,8 @@
-
import datetime
-import hashlib
import operator
-import os
import re
import smtplib
-from cStringIO import StringIO
-from PIL import Image
-
-from django.conf import settings
from django.contrib import auth
from django.core.urlresolvers import reverse
from django.db import transaction
@@ -310,37 +303,6 @@ def derive_username(nickname):
return nickname
-@must_be_owner
-def upload_profile_photo(request, username):
- person = get_object_or_404(DjangoPerson, user__username=username)
- if request.method == 'POST':
- form = PhotoUploadForm(request.POST, request.FILES)
- if form.is_valid():
- # Figure out what type of image it is
- image_content = request.FILES['photo'].read()
- format = Image.open(StringIO(image_content)).format
- format = format.lower().replace('jpeg', 'jpg')
- filename = hashlib.md5(image_content).hexdigest() + '.' + format
- # Save the image
- path = os.path.join(settings.MEDIA_ROOT, 'profiles', filename)
- open(path, 'w').write(image_content)
- person.photo = 'profiles/%s' % filename
- person.save()
- return redirect(reverse('upload_done', args=[username]))
- else:
- form = PhotoUploadForm()
- return render(request, 'upload_profile_photo.html', {
- 'form': form,
- 'person': person,
- })
-
-
-@must_be_owner
-def upload_done(request, username):
- "Using a double redirect to try and stop back button from re-uploading"
- return redirect(reverse('user_profile', args=[username]))
-
-
class CountryView(generic.DetailView):
template_name = 'country.html'
context_object_name = 'country'
@@ -539,6 +501,25 @@ def get_initial(self):
edit_location = must_be_owner(EditLocationView.as_view())
+class UploadProfilePhoto(DjangoPersonEditViewBase):
+ form_class = PhotoUploadForm
+ template_name = 'upload_profile_photo.html'
+
+ def get_success_url(self):
+ return reverse('upload_done', args=[self.kwargs['username']])
+upload_profile_photo = must_be_owner(UploadProfilePhoto.as_view())
+
+
+class UploadDone(generic.RedirectView):
+ "Using a double redirect to try and stop back button from re-uploading"
+ permanent = False
+
+ def get_redirect_url(self, username):
+ user = self.request.user
+ return reverse('user_profile', args=[user.username])
+upload_done = must_be_owner(UploadDone.as_view())
+
+
class SkillCloudView(generic.TemplateView):
template_name = 'skills.html'
View
1  requirements.txt
@@ -3,3 +3,4 @@ geopy==0.94.1
python-openid==2.2.5
django-tagging==0.3.1
sorl-thumbnail==3.2.5
+django-storages==1.1.3
View
4 urls.py
@@ -86,10 +86,10 @@ def perm_redirect(url):
url(r'^(?P<username>[a-z0-9]{3,})/finding/$',
views.edit_finding, name='edit_finding'),
- url(r'^([a-z0-9]{3,})/upload/$',
+ url(r'^(?P<username>[a-z0-9]{3,})/upload/$',
views.upload_profile_photo, name='upload_profile_photo'),
- url(r'^([a-z0-9]{3,})/upload/done/$',
+ url(r'^(?P<username>[a-z0-9]{3,})/upload/done/$',
views.upload_done, name='upload_done'),
)
Please sign in to comment.
Something went wrong with that request. Please try again.