From f691ef58933bf33033389a1a468f655af19c1e16 Mon Sep 17 00:00:00 2001 From: holyantony Date: Fri, 8 May 2015 11:59:21 +0530 Subject: Subject: Profile updation and Email notification Description: 1. Confirmation link on registration via email 2. Profile updation on registration confirmation 3. Email notification posting question and answer --- forums/forms.py | 29 +++++++- forums/urls.py | 3 + forums/views.py | 112 ++++++++++++++++++++++++++---- static/forums/templates/profile.html | 86 +++++++++++++++++++++++ static/forums/templates/view-profile.html | 42 +++++++++++ static/website/css/chosen.min.css | 3 + website/models.py | 12 +++- website/views.py | 5 +- 8 files changed, 277 insertions(+), 15 deletions(-) create mode 100644 static/forums/templates/profile.html create mode 100644 static/forums/templates/view-profile.html create mode 100644 static/website/css/chosen.min.css diff --git a/forums/forms.py b/forums/forms.py index 6bfb184..3404ac2 100644 --- a/forums/forms.py +++ b/forums/forms.py @@ -11,7 +11,7 @@ from django.utils.translation import ugettext_lazy as _ from django.core.validators import MinLengthValidator, MinValueValidator, \ RegexValidator, URLValidator from django.template.defaultfilters import filesizeformat - +from website.models import Profile class UserLoginForm(forms.Form): @@ -35,6 +35,33 @@ class UserLoginForm(forms.Form): cleaned_data['user'] = user return cleaned_data +class ProfileForm(forms.ModelForm): + class Meta: + model = Profile + exclude = ['user', 'confirmation_code'] + + # def clean_picture(self): + # if 'picture' in self.cleaned_data and not \ + # self.cleaned_data['picture']: + # raise forms.ValidationError("Profile picture required!") + + first_name = forms.CharField() + last_name = forms.CharField() + + + + def __init__(self, user, *args, **kwargs): + initial = '' + if 'instance' in kwargs: + initial = kwargs["instance"] + if 'user' in kwargs: + user = kwargs["user"] + del kwargs["user"] + + super(ProfileForm, self).__init__(*args, **kwargs) + self.fields['first_name'].initial = user.first_name + self.fields['last_name'].initial = user.last_name + class RegisterForm(forms.Form): username = forms.CharField( diff --git a/forums/urls.py b/forums/urls.py index 3f257ea..31c679b 100644 --- a/forums/urls.py +++ b/forums/urls.py @@ -20,4 +20,7 @@ urlpatterns = patterns('', url(r'^accounts/logout/', 'forums.views.user_logout', name='user_logout'), url(r'^accounts/register/', 'forums.views.account_register', name='user_register'), url(r'^migrate', 'migrate_spoken.views.chenage_drupal_userid_spoken', name='chenage_drupal_userid_spoken'), + url(r"^accounts/confirm/(?P\w+)/(?P[\w. @-]+)/$", 'forums.views.confirm', name='confirm'), + url(r"^accounts/profile/(?P[\w. @-]+)/$", 'forums.views.account_profile', name='profile'), + url(r"^accounts/view-profile/(?P[\w. @-]+)/$", 'forums.views.account_view_profile', name='view_profile'), ) diff --git a/forums/views.py b/forums/views.py index e757ab9..f602a55 100644 --- a/forums/views.py +++ b/forums/views.py @@ -1,6 +1,6 @@ from django.http import HttpResponse, HttpResponseRedirect from django.contrib.auth import login, logout, authenticate -from django.shortcuts import render_to_response +from django.shortcuts import render_to_response , render from django.core.context_processors import csrf from django.template import RequestContext from django.contrib.auth.decorators import login_required @@ -8,15 +8,10 @@ from django.contrib.auth import authenticate, login, logout from django.core.mail import EmailMultiAlternatives from django.contrib import messages from django.utils import timezone - - from django.conf import settings - - - import random, string - from forums.forms import * +from website.models import * def account_register(request): context = {} @@ -38,9 +33,9 @@ def account_register(request): user.is_active = True user.save() confirmation_code = ''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for x in range(33)) - #p = Profile(user=user, confirmation_code=confirmation_code) - #p.save() - #send_registration_confirmation(user) + p = Profile(user=user, confirmation_code=confirmation_code) + p.save() + send_registration_confirmation(user) messages.success(request, """ Please confirm your registration by clicking on the activation link which has been sent to your registered email id. """) @@ -54,6 +49,98 @@ def account_register(request): } context.update(csrf(request)) return render_to_response('forums/templates/user-register.html', context) + +def confirm(request, confirmation_code, username): + try: + user = User.objects.get(username=username) + profile = Profile.objects.get(user=user) + #if profile.confirmation_code == confirmation_code and user.date_joined > (timezone.now()-timezone.timedelta(days=1)): + if profile.confirmation_code == confirmation_code: + user.is_active = True + user.save() + user.backend='django.contrib.auth.backends.ModelBackend' + login(request,user) + print "In if" + messages.success(request, "Your account has been activated!. Please update your profile to complete your registration") + return HttpResponseRedirect('/accounts/profile/'+user.username) + else: + print "In else" + messages.success(request, "Something went wrong!. Please try again!") + return HttpResponseRedirect('/') + except Exception, e: + print "In excepw" + messages.success(request, "Your account not activated!. Please try again!") + return HttpResponseRedirect('/') + +@login_required +def account_logout(request): + context = RequestContext(request) + logout(request) + return HttpResponseRedirect('/') + +@login_required +def account_profile(request, username): + user = request.user + profile = Profile.objects.get(user_id=user.id) + #old_file_path = settings.MEDIA_ROOT + str(profile.picture) + #new_file_path = None + if request.method == 'POST': + form = ProfileForm(user, request.POST) + if form.is_valid(): + user.first_name = request.POST['first_name'] + user.last_name = request.POST['last_name'] + user.save() + form_data = form.save(commit=False) + form_data.user_id = user.id + + # if 'picture-clear' in request.POST and request.POST['picture-clear']: + # #if not old_file == new_file: + # if os.path.isfile(old_file_path): + # os.remove(old_file_path) + # + # if 'picture' in request.FILES: + # form_data.picture = request.FILES['picture'] + + form_data.save() + + """if 'picture' in request.FILES: + size = 128, 128 + filename = str(request.FILES['picture']) + ext = os.path.splitext(filename)[1] + if ext != '.pdf' and ext != '': + im = Image.open(settings.MEDIA_ROOT + str(form_data.picture)) + im.thumbnail(size, Image.ANTIALIAS) + ext = ext[1:] + + mimeType = ext.upper() + if mimeType == 'JPG': + mimeType = 'JPEG' + im.save(settings.MEDIA_ROOT + "user/" + str(user.id) + "/" + str(user.id) + "-thumb." + ext, mimeType) + form_data.thumb = 'user/' + str(user.id)+ '/' + str(user.id) + '-thumb.' + ext + form_data.save()""" + messages.success(request, "Your profile has been updated!") + return HttpResponseRedirect("/accounts/view-profile/" + user.username) + + context = {'form':form} + return render(request, 'forums/templates/profile.html', context) + else: + context = {} + context.update(csrf(request)) + instance = Profile.objects.get(user_id=user.id) + context['form'] = ProfileForm(user, instance = instance) + return render(request, 'forums/templates/profile.html', context) + +@login_required +def account_view_profile(request, username): + + user = User.objects.get(username = username) + profile = Profile.objects.filter(user = user)[0] + context = { + 'profile' : profile, + 'media_url' : settings.MEDIA_URL, + } + return render(request, 'forums/templates/view-profile.html', context) + def send_registration_confirmation(user): p = Profile.objects.get(user=user) @@ -69,14 +156,15 @@ def send_registration_confirmation(user): IIT Bombay. """.format( user.username, - "http://spoken-tutorial.org", - "http://spoken-tutorial.org/accounts/confirm/" + str(p.confirmation_code) + "/" + user.username + "http://fossee.in", + "http://localhost:8000/accounts/confirm/" + str(p.confirmation_code) + "/" + user.username ) email = EmailMultiAlternatives( subject, message, 'sysads@fossee.in', to = [user.email], bcc = [], cc = [], headers={'Reply-To': 'no-replay@spoken-tutorial.org', "Content-type":"text/html;charset=iso-8859-1"} ) + print message email.attach_alternative(message, "text/html") try: result = email.send(fail_silently=False) diff --git a/static/forums/templates/profile.html b/static/forums/templates/profile.html new file mode 100644 index 0000000..ffb500a --- /dev/null +++ b/static/forums/templates/profile.html @@ -0,0 +1,86 @@ +{% extends 'website/templates/base.html' %} +{% load widget_tweaks %} +{% load static %} +{% block title %}User Profile{% endblock %} +{% block cssblock %}{% endblock %} +{% block heading %} + User Profile +{% endblock %} + +{% block content %} +
+
+ +
+
+ +{% endblock %} + + diff --git a/static/forums/templates/view-profile.html b/static/forums/templates/view-profile.html new file mode 100644 index 0000000..afed394 --- /dev/null +++ b/static/forums/templates/view-profile.html @@ -0,0 +1,42 @@ +{% extends 'website/templates/base.html' %} +{% load widget_tweaks %} +{% load static %} +{% block title %}User Profile{% endblock %} +{% block cssblock %} + + +{% endblock %} +{% block heading %} + User Profile +{% endblock %} + +{% block content %} +
+
+ +
+
+
First name
+
{% if profile.user.first_name %}{{ profile.user.first_name }}{% else %}-{% endif %}
+ +
Last name
+
{% if profile.user.last_name %}{{ profile.user.last_name }}{% else %}-{% endif %}
+ +
Profile created on
+
{{ profile.created }}
+ +
+
+
+
+{% endblock %} + + diff --git a/static/website/css/chosen.min.css b/static/website/css/chosen.min.css new file mode 100644 index 0000000..0347419 --- /dev/null +++ b/static/website/css/chosen.min.css @@ -0,0 +1,3 @@ +/* Chosen v1.1.0 | (c) 2011-2013 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ + +.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;zoom:1;*display:inline;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chosen-container .chosen-drop{position:absolute;top:100%;left:-9999px;z-index:1010;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15)}.chosen-container.chosen-with-drop .chosen-drop{left:0}.chosen-container a{cursor:pointer}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:23px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),color-stop(100%,#f4f4f4));background:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(../images/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(../images/chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:#fff url(../images/chosen-sprite.png) no-repeat 100% -20px;background:url(../images/chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:-webkit-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-moz-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-o-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;width:100%;height:auto!important;height:1%;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(1%,#eee),color-stop(15%,#fff));background-image:-webkit-linear-gradient(#eee 1%,#fff 15%);background-image:-moz-linear-gradient(#eee 1%,#fff 15%);background-image:-o-linear-gradient(#eee 1%,#fff 15%);background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:5px;height:15px;outline:0;border:0!important;background:transparent!important;box-shadow:none;color:#666;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-multi .chosen-choices li.search-field .default{color:#999}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 0 3px 5px;padding:3px 20px 3px 5px;border:1px solid #aaa;border-radius:3px;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(../images/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#eee),color-stop(80%,#fff));background-image:-webkit-linear-gradient(#eee 20%,#fff 80%);background-image:-moz-linear-gradient(#eee 20%,#fff 80%);background-image:-o-linear-gradient(#eee 20%,#fff 80%);background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:0;background:transparent}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#111!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single-nosearch .chosen-search,.chosen-rtl .chosen-drop{left:9999px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:0}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:#fff url(../images/chosen-sprite.png) no-repeat -30px -20px;background:url(../images/chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:144dpi){.chosen-rtl .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-container-single .chosen-search input[type=text],.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span{background-image:url(../images/chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}} diff --git a/website/models.py b/website/models.py index da87cb5..c7e43aa 100644 --- a/website/models.py +++ b/website/models.py @@ -3,7 +3,7 @@ from django.db import models from django.contrib.auth.models import User from django.contrib.auth import get_user_model -User = get_user_model() + class FossCategory(models.Model): name = models.CharField(max_length=100) @@ -85,3 +85,13 @@ class Notification(models.Model): def poster(self): user = User.objects.get(id=self.pid) return user.username + +class Profile(models.Model): + user = models.ForeignKey(User) + confirmation_code = models.CharField(max_length=255) + phone = models.CharField(max_length=20, null=True) + address = models.TextField(null=True) + created = models.DateTimeField(auto_now_add=True) + + class Meta: + app_label = 'website' diff --git a/website/views.py b/website/views.py index 3009a6a..de93b7f 100644 --- a/website/views.py +++ b/website/views.py @@ -251,7 +251,8 @@ def new_question(request): question.body = cleaned_data['body'].encode('unicode_escape') question.views= 1 question.save() - + print "question" + print question.id # Sending email when a new question is asked subject = 'New Forum Question' message = """ @@ -271,6 +272,8 @@ def new_question(request): ['team@fossee.in'], headers={"Content-type":"text/html;charset=iso-8859-1"} ) + print message + print "****************" email.attach_alternative(message, "text/html") email.send(fail_silently=True) # End of email send -- cgit