diff options
Diffstat (limited to 'project/kiwipycon/user')
-rw-r--r-- | project/kiwipycon/user/__init__.py | 0 | ||||
-rw-r--r-- | project/kiwipycon/user/admin.py | 17 | ||||
-rw-r--r-- | project/kiwipycon/user/forms.py | 135 | ||||
-rw-r--r-- | project/kiwipycon/user/migrations/0001_initial.py | 44 | ||||
-rw-r--r-- | project/kiwipycon/user/migrations/__init__.py | 0 | ||||
-rw-r--r-- | project/kiwipycon/user/models.py | 36 | ||||
-rw-r--r-- | project/kiwipycon/user/utils.py | 122 | ||||
-rw-r--r-- | project/kiwipycon/user/views.py | 238 |
8 files changed, 592 insertions, 0 deletions
diff --git a/project/kiwipycon/user/__init__.py b/project/kiwipycon/user/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/kiwipycon/user/__init__.py diff --git a/project/kiwipycon/user/admin.py b/project/kiwipycon/user/admin.py new file mode 100644 index 0000000..c72a5b5 --- /dev/null +++ b/project/kiwipycon/user/admin.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#django +from django.contrib import admin + +#kiwipycon +from .models import UserProfile + +class UserProfileAdmin(admin.ModelAdmin): + list_display = ('user', 'email', 'url', 'about') + + def email(self, obj): + return obj.user.email + +admin.site.register(UserProfile, UserProfileAdmin) + diff --git a/project/kiwipycon/user/forms.py b/project/kiwipycon/user/forms.py new file mode 100644 index 0000000..46ad2f6 --- /dev/null +++ b/project/kiwipycon/user/forms.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#django +from django import forms +from django.contrib.auth.models import User + +class RegistrantForm(forms.Form): + """Form to register an attendee + """ + username = forms.RegexField(label="Nickname", max_length=30, + regex=r'^\w+$', + help_text = "30 characters or fewer. Alphanumeric" \ + + " characters only (letters, digits and underscores).", + error_message = "This value must contain only letters, numbers and underscores.") + name = forms.CharField(label=u"Name", max_length=50, required=True) + email = forms.EmailField(label=u"E-mail", max_length=50, required=True) + + def clean_email(self): + """Validates that the entered e-mail is unique. + """ + email = self.cleaned_data.get("email") + if email and User.objects.filter(email=email).count() > 0: + raise forms.ValidationError( + u"That email address is already in use. Are you a member of " \ + "site? Please log in.") + + return email + + def clean_username(self): + """Validates that the entered username is unique. + """ + username = self.cleaned_data.get("username") + if username and User.objects.filter(username=username).count() > 0: + raise forms.ValidationError( + u"That username is already in use.") + + return username + +class RegisterForm(forms.Form): + """Form to register speaker + """ + username = forms.RegexField(label="Username", max_length=30, + regex=r'^\w+$', + help_text = "Required. 30 characters or fewer. Alphanumeric" \ + + " characters only (letters, digits and underscores).", + error_message = "This value must contain only letters, numbers and underscores.") + first_name = forms.CharField(label=u"First name", max_length=50) + last_name = forms.CharField(label=u"Last name", max_length=50) + email = forms.EmailField(label=u"E-mail", max_length=50) + url = forms.URLField(required=False) + about = forms.CharField(label=u'Short Bio', max_length=50, required=False) + photo = forms.FileField(label=u'Profile Photo', required=False) + password_1 = forms.CharField( + label=u"Password", widget=forms.PasswordInput(), max_length=20) + password_2 = forms.CharField( + label=u"Confirm password", widget=forms.PasswordInput(), max_length=20) + + def clean_password_2(self): + """Validates that password 1 and password 2 are the same. + """ + p1 = self.cleaned_data.get('password_1') + p2 = self.cleaned_data.get('password_2') + + if not (p1 and p2 and p1 == p2): + raise forms.ValidationError(u"The two passwords do not match.") + + return p2 + + def clean_email(self): + """Validates that the entered e-mail is unique. + """ + email = self.cleaned_data.get("email") + if email and User.objects.filter(email=email).count() > 0: + raise forms.ValidationError( + u"That email address is already in use.") + + return email + + def clean_username(self): + """Validates that the entered username is unique. + """ + username = self.cleaned_data.get("username") + if username and User.objects.filter(username=username).count() > 0: + raise forms.ValidationError( + u"That username is already in use.") + + return username + +class EditProfileForm(forms.Form): + """Edit user profile form + """ + first_name = forms.CharField(max_length=50) + last_name = forms.CharField(max_length=50) + email = forms.EmailField(max_length=50) + email2 = forms.CharField(widget=forms.HiddenInput) + url = forms.URLField(required=False) + about = forms.CharField(label=u'Short Bio', + widget=forms.Textarea, required=False) + photo = forms.FileField(label=u'Profile Photo', + required=False) + + def clean_email(self): + """Validates that the entered e-mail is unique. + """ + email = self.cleaned_data.get("email") + email2 = self.data.get("email2").strip() + print email, email2 + if email != email2: # email has been changed + if email and User.objects.filter(email=email).count() > 0: + raise forms.ValidationError( + u"That email address is already in use.") + + return email + +class UsernameForm(forms.Form): + """Form to edit email address + """ + username = forms.RegexField(label="Username", max_length=30, + regex=r'^\w+$', + help_text = "Required. 30 characters or fewer. Alphanumeric" \ + + " characters only (letters, digits and underscores).", + error_message = "This value must contain only letters, numbers and underscores.") + + def clean_username(self): + """Validates that the entered username is unique. + """ + username = self.cleaned_data.get("username") + if username and User.objects.filter(username=username).count() > 0: + raise forms.ValidationError( + u"That username is already in use.") + + return username + + diff --git a/project/kiwipycon/user/migrations/0001_initial.py b/project/kiwipycon/user/migrations/0001_initial.py new file mode 100644 index 0000000..8cb8788 --- /dev/null +++ b/project/kiwipycon/user/migrations/0001_initial.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +from south.db import db +from django.db import models +from project.kiwipycon.user.models import * + +class Migration: + + def forwards(self, orm): + + # Adding model 'UserProfile' + db.create_table('user_userprofile', ( + ('id', models.AutoField(primary_key=True)), + ('user', models.ForeignKey(orm['auth.User'], unique=True)), + ('url', models.URLField(verify_exists=False, blank=True)), + ('photo', models.CharField(max_length=64, blank=True)), + ('about', models.TextField(blank=True)), + )) + db.send_create_signal('user', ['UserProfile']) + + + + def backwards(self, orm): + + # Deleting model 'UserProfile' + db.delete_table('user_userprofile') + + + + models = { + 'auth.user': { + '_stub': True, + 'id': ('models.AutoField', [], {'primary_key': 'True'}) + }, + 'user.userprofile': { + 'about': ('models.TextField', [], {'blank': 'True'}), + 'id': ('models.AutoField', [], {'primary_key': 'True'}), + 'photo': ('models.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'url': ('models.URLField', [], {'verify_exists': 'False', 'blank': 'True'}), + 'user': ('models.ForeignKey', ['User'], {'unique': 'True'}) + } + } + + complete_apps = ['user'] diff --git a/project/kiwipycon/user/migrations/__init__.py b/project/kiwipycon/user/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/kiwipycon/user/migrations/__init__.py diff --git a/project/kiwipycon/user/models.py b/project/kiwipycon/user/models.py new file mode 100644 index 0000000..85cf762 --- /dev/null +++ b/project/kiwipycon/user/models.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#django +from django.db import models +from django.conf import settings +from django.db.models.signals import post_save +from django.contrib.auth.models import User + +class UserProfile(models.Model): + """ + Extend atributes for django User + """ + user = models.ForeignKey(User, unique=True) + url = models.URLField(blank=True, verify_exists=False) + photo = models.CharField(max_length=64, blank=True) + about = models.TextField(blank=True) + + def __unicode__(self): + return 'UserProfile for user: <%s %s> %s' % (self.user.first_name, + self.user.last_name, self.user.email) + + def fullname(self): + return '%s %s' % (self.user.first_name, self.user.last_name) + +def add_profile(sender, instance, signal, *args, **kwargs): + """Create user profile on create of new user""" + if not instance.is_superuser: + try: + profile, new = UserProfile.objects.get_or_create(user=instance) + if new: + profile.save() + except: + pass + +post_save.connect(add_profile, sender=User, weak=False) diff --git a/project/kiwipycon/user/utils.py b/project/kiwipycon/user/utils.py new file mode 100644 index 0000000..b912a7b --- /dev/null +++ b/project/kiwipycon/user/utils.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#python imports +import os + +#django +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist + +#django.contrib +from django.contrib.auth.models import User + +#PIL +from PIL import Image + + +def kiwipycon_createregistrant(request, data): + """Create user""" + email = data.get("email") + name = data.get("name") + username = data.get("username") + + n = name.split(" ") + if len(n) > 1: + first_name = ' '.join(n[:-1]) + last_name = n[-1] + else: + first_name = '' + last_name = n[0] + + + # Create user + user = User.objects.create_user(username=username, email=email) + user.first_name = first_name + user.last_name = last_name + user.save() + + return user + +def kiwipycon_createuser(request, data): + """Create user""" + email = data.get("email") + username = data.get("username") + password = data.get("password_1") + password = data.get("password_1") + + # Create user + user = User.objects.create_user( + username=username, email=email, password=password) + user.first_name = data.get("first_name") + user.last_name = data.get("last_name") + user.save() + + # Log in user + from django.contrib.auth import authenticate + user = authenticate(username=username, password=password) + + from django.contrib.auth import login + login(request, user) + + profile = user.get_profile() + photo = request.FILES.get('photo', None) + filename= None + if photo: + filename = handle_uploaded_photo(user, request.FILES['photo']) + if filename: + profile.photo = filename + print photo, filename + + profile.url = data.get("url") + profile.about = data.get("about") + profile.save() + + return user + +def handle_uploaded_photo(user, ufile): + usermedia = settings.USER_MEDIA_ROOT + filename = ufile.name + ext = filename.split('.')[-1] + filesize = ufile.size + filecontent = ufile.read() + userfilename = 'user-%d.%s' % (user.id, ext) + if not filecontent: + return None + + #save + foutname = os.path.join(usermedia, userfilename) + + fout = file(foutname, 'wb') + fout.write(filecontent) + fout.close() + + # crop and resize + image = Image.open(foutname) + pw = image.size[0] + ph = image.size[1] + nw = nh = 80 + if (pw, ph) != (nw, nh): + pr = float(pw) / float(ph) + nr = float(nw) / float(nh) + + if pr > nr: + # photo aspect is wider than destination ratio + tw = int(round(nh * pr)) + image = image.resize((tw, nh), Image.ANTIALIAS) + l = int(round(( tw - nw ) / 2.0)) + image = image.crop((l, 0, l + nw, nh)) + elif pr < nr: + # photo aspect is taller than destination ratio + th = int(round(nw / pr)) + image = image.resize((nw, th), Image.ANTIALIAS) + t = int(round(( th - nh ) / 2.0)) + print((0, t, nw, t + nh)) + image = image.crop((0, t, nw, t + nh)) + else: + # photo aspect matches the destination ratio + image = image.resize((nw, nh), Image.ANTIALIAS) + + image.save(str(foutname)) + return userfilename + diff --git a/project/kiwipycon/user/views.py b/project/kiwipycon/user/views.py new file mode 100644 index 0000000..e9a0454 --- /dev/null +++ b/project/kiwipycon/user/views.py @@ -0,0 +1,238 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import +#python +from urlparse import urlparse +import urllib +import os + +#django +from django.conf import settings +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.core.urlresolvers import reverse +from django.db.models.signals import post_save + +#django.contrib +from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.forms import PasswordChangeForm +from django.core.exceptions import ObjectDoesNotExist + +#PIL +from PIL import Image + +#kiwipycon +from project.kiwipycon.utils import set_message_cookie +from project.kiwipycon.talk.models import Talk +from project.kiwipycon.registration.models import Registration +from project.kiwipycon.registration.models import Wifi +from project.kiwipycon.registration.forms import WifiForm +from project.kiwipycon.sponsor.models import Sponsor + +from .utils import kiwipycon_createuser +from .utils import handle_uploaded_photo +from .forms import RegisterForm +from .forms import EditProfileForm +from .forms import UsernameForm + +@login_required +def account(request, template_name="user/account.html"): + """Displays the main screen of the current user's account. + """ + user = request.user + profile = user.get_profile() + + talks = Talk.objects.filter(speaker=user) + try: + registration = Registration.objects.get(registrant=user) + except ObjectDoesNotExist: + registration = None + try: + wifiobj = Wifi.objects.get(user=user) + except ObjectDoesNotExist: + wifiobj = None + + if profile.photo: + photo = os.path.join(settings.USER_MEDIA_URL, profile.photo) + else: + photo = '/img/user-default.png' + + qstring = "" + + wifi_comment = None + if wifiobj: + wifi_form = False + else: + if request.method == "POST": + wifi_form = WifiForm(request.POST) + if wifi_form.is_valid(): + wifi_form.save(user) + wifi_comment = 'Thanks, your wifi preference has been saved' + wifi_form = None + else: + wifi_form = WifiForm() + + return render_to_response(template_name, RequestContext(request, { + "form" : wifi_form, "comment": wifi_comment, + "user" : user, "profile" : profile, "photo" : photo, + "talks" : talks, "registration" : registration, + })) + +@login_required +def edit_profile(request, template_name="user/editprofile.html"): + """Allows user to edit profile + """ + user = request.user + profile = user.get_profile() + + if request.method == "POST": + form = EditProfileForm(data=request.POST, + files=request.FILES) + + if form.is_valid(): + photo = request.FILES.get('photo', None) + filename= None + if photo: + filename = handle_uploaded_photo(user, request.FILES['photo']) + if filename: + profile.photo = filename + + user.email = form.data.get("email") + user.first_name = form.data.get("first_name") + user.last_name = form.data.get("last_name") + user.save() + + profile.url = form.data.get("url") + profile.about = form.data.get("about") + profile.save() + + redirect_to = reverse("kiwipycon_account") + return set_message_cookie(redirect_to, + msg = u"Your profile has been changed.") + + else: + form = EditProfileForm(initial={"email" : user.email, + "email2" : user.email, # hidden field + "first_name" : user.first_name, + "last_name" : user.last_name, + "url" : profile.url, + "about" : profile.about, + }) + + return render_to_response(template_name, RequestContext(request, { + "form": form + })) + +def login(request, template_name="user/login.html"): + """Custom view to login or register/login a user. + Integration of register and login form + It uses Django's standard AuthenticationForm, though. + """ + user = request.user + if user.is_authenticated(): + redirect_to = reverse("kiwipycon_account") + return set_message_cookie(redirect_to, + msg = u"Redirected to account from login form.") + + # Using Djangos default AuthenticationForm + login_form = AuthenticationForm() + register_form = RegisterForm() + + if request.POST.get("action") == "login": + login_form = AuthenticationForm(data=request.POST) + + if login_form.is_valid(): + redirect_to = request.POST.get("next") + # Light security check -- make sure redirect_to isn't garbage. + if not redirect_to or '//' in redirect_to or ' ' in redirect_to: + redirect_to = reverse("kiwipycon_account") + + from django.contrib.auth import login + login(request, login_form.get_user()) + + return set_message_cookie(redirect_to, msg = u"You have been logged in.") + + elif request.POST.get("action") == "register": + register_form = RegisterForm(data=request.POST) + if register_form.is_valid(): + + user = kiwipycon_createuser(request, register_form.data) + + redirect_to = request.POST.get("next") + if not redirect_to or '//' in redirect_to or ' ' in redirect_to: + redirect_to = reverse("kiwipycon_account") + + return set_message_cookie( + redirect_to, msg = u"You have been registered and logged in.") + + # Get next_url + next_url = request.REQUEST.get("next") + if next_url is None: + next_url = request.META.get("HTTP_REFERER") + if next_url is None: + next_url = reverse("kiwipycon_account") + # Get just the path of the url. See django.contrib.auth.views.login for more + next_url = urlparse(next_url) + next_url = next_url[2] + + try: + login_form_errors = login_form.errors["__all__"] + except KeyError: + login_form_errors = None + + return render_to_response(template_name, RequestContext(request, { + "login_form" : login_form, + "login_form_errors" : login_form_errors, + "register_form" : register_form, + "next_url" : next_url, + })) + +def logout(request): + """Custom method to logout a user. + + The reason to use a custom logout method is just to provide a login and a + logoutmethod on one place. + """ + from django.contrib.auth import logout + logout(request) + + redirect_to = '/' + return set_message_cookie(redirect_to, msg = u"You have been logged out.") + +@login_required +def password(request, template_name="user/password.html"): + """Changes the password of current user. + """ + if request.method == "POST": + form = PasswordChangeForm(request.user, request.POST) + if form.is_valid(): + form.save() + redirect_to = reverse("kiwipycon_account") + return set_message_cookie(redirect_to, + msg = u"Your password has been changed.") + else: + form = PasswordChangeForm(request.user) + + return render_to_response(template_name, RequestContext(request, { + "form" : form + })) + +@login_required +def username(request, template_name="user/username.html"): + """Saves the username from the data form. + """ + if request.method == "POST": + username_form = UsernameForm(initial={"username" : request.user.username}, data=request.POST) + if username_form.is_valid(): + request.user.username = username_form.cleaned_data.get("username") + request.user.save() + redirect_to = reverse("kiwipycon_account") + return set_message_cookie(redirect_to, + msg = u"Your username has been changed.") + else: + username_form = UsernameForm(initial={"username" : request.user.username}) + + return render_to_response(template_name, RequestContext(request, { + "form": username_form + })) + |