User Registration & Email Authantication
Basic user registration system and email authantication. Change-Id: Iaa4266edaf78b5c42c4aafc0de2d1f11f9f6c4f5
This commit is contained in:
parent
3da226dce3
commit
d3fa9b79b4
@ -0,0 +1,36 @@
|
|||||||
|
import re
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
|
||||||
|
class UserRegisterForm(forms.Form):
|
||||||
|
email = forms.EmailField(label='Email')
|
||||||
|
password1 = forms.CharField(
|
||||||
|
label='Password',
|
||||||
|
widget=forms.PasswordInput(),
|
||||||
|
)
|
||||||
|
password2 = forms.CharField(
|
||||||
|
label='Password (Again)',
|
||||||
|
widget=forms.PasswordInput(),
|
||||||
|
)
|
||||||
|
tos = forms.BooleanField(
|
||||||
|
required=True,
|
||||||
|
error_messages={'required': 'You must accept TOS.'}
|
||||||
|
)
|
||||||
|
|
||||||
|
def clean_email(self):
|
||||||
|
email = self.cleaned_data['email']
|
||||||
|
try:
|
||||||
|
User.objects.get(email=email)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
return email
|
||||||
|
raise forms.ValidationError('Email address is not available.')
|
||||||
|
|
||||||
|
def clean_password2(self):
|
||||||
|
if 'password1' in self.cleaned_data:
|
||||||
|
password1 = self.cleaned_data['password1']
|
||||||
|
password2 = self.cleaned_data['password2']
|
||||||
|
if password1 == password2:
|
||||||
|
return password2
|
||||||
|
raise forms.ValidationError('Password do not match.')
|
@ -1,5 +1,4 @@
|
|||||||
from django.conf.urls import url
|
from django.conf.urls import include, url
|
||||||
from django.contrib import admin
|
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
@ -8,4 +7,6 @@ urlpatterns = [
|
|||||||
url(r'^$', views.index, name='index'),
|
url(r'^$', views.index, name='index'),
|
||||||
url(r'^login/$', auth_views.login, {'template_name': 'authcp/login.html'}, name='login'),
|
url(r'^login/$', auth_views.login, {'template_name': 'authcp/login.html'}, name='login'),
|
||||||
url(r'^logout/$', auth_views.logout, name='logout'),
|
url(r'^logout/$', auth_views.logout, name='logout'),
|
||||||
|
url(r'^register/$', views.register_user, name='register'),
|
||||||
|
url(r'^register-success/$', views.register_success, name='register-success'),
|
||||||
]
|
]
|
||||||
|
@ -1,6 +1,82 @@
|
|||||||
from django.shortcuts import render
|
import random, hashlib, datetime
|
||||||
|
|
||||||
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.core.mail import EmailMultiAlternatives
|
||||||
|
from django.template import Context
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
from .forms import UserRegisterForm
|
||||||
|
from user_profile.models import Profile
|
||||||
|
|
||||||
|
# email sending function
|
||||||
|
def send_email(con,subject,email_to,email_from):
|
||||||
|
c = Context(con)
|
||||||
|
text_content = render_to_string('mail/user_register_welcome.txt', c)
|
||||||
|
html_content = render_to_string('mail/user_register_welcome.html', c)
|
||||||
|
|
||||||
|
email = EmailMultiAlternatives(subject,text_content,email_from)
|
||||||
|
email.attach_alternative(html_content, "text/html")
|
||||||
|
email.to = [email_to]
|
||||||
|
email.send()
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
return render(request, "authcp/index.html", {})
|
return render(request, "authcp/index.html", {})
|
||||||
|
|
||||||
|
def register_user(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = UserRegisterForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
u=User.objects.create_user(
|
||||||
|
form.cleaned_data['email'],
|
||||||
|
form.cleaned_data['email'],
|
||||||
|
form.cleaned_data['password2'],
|
||||||
|
)
|
||||||
|
u.is_active=False
|
||||||
|
u.save()
|
||||||
|
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
|
||||||
|
usernamesalt=form.cleaned_data['email']
|
||||||
|
profile=Profile.objects.get(user_id=u.id)
|
||||||
|
profile.activation_key=hashlib.sha1(salt+usernamesalt).hexdigest()
|
||||||
|
profile.key_expires=datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(days=2),
|
||||||
|
"%Y-%m-%d %H:%M:%S")
|
||||||
|
profile.save()
|
||||||
|
send_email({'u': u, 'profil': profile},
|
||||||
|
'Welcome to our cloud',
|
||||||
|
u.email,
|
||||||
|
settings.DEFAULT_EMAIL_FROM,
|
||||||
|
)
|
||||||
|
return render(request,
|
||||||
|
'authcp/success.html',
|
||||||
|
{'u': u, 'profil': profile})
|
||||||
|
else:
|
||||||
|
print(form.errors)
|
||||||
|
else:
|
||||||
|
form = UserRegisterForm()
|
||||||
|
return render(request, 'authcp/register.html', {'form': form})
|
||||||
|
|
||||||
|
def register_success(request):
|
||||||
|
return render(request, 'authcp/success.html', {})
|
||||||
|
|
||||||
|
def activation(request, key):
|
||||||
|
activation_expired=False
|
||||||
|
already_active=False
|
||||||
|
profile=get_object_or_404(Profile, activation_key=key)
|
||||||
|
if profile.user.is_active == False:
|
||||||
|
if timezone.now() > profile.key_expires:
|
||||||
|
# Display: offer the user to send a new activation link
|
||||||
|
activation_expired=True
|
||||||
|
id_user=profile.user.id
|
||||||
|
# Activation successful
|
||||||
|
else:
|
||||||
|
profile.user.is_active=True
|
||||||
|
profile.user.save()
|
||||||
|
# If user is already active, simply display error message
|
||||||
|
else:
|
||||||
|
# Display : error message
|
||||||
|
already_active=True
|
||||||
|
return render(request, 'authcp/activation.html', locals())
|
@ -27,7 +27,7 @@ DEBUG = True
|
|||||||
|
|
||||||
ALLOWED_HOSTS = [
|
ALLOWED_HOSTS = [
|
||||||
'dash-stack',
|
'dash-stack',
|
||||||
'198.211.127.189',
|
'127.0.0.1',
|
||||||
]
|
]
|
||||||
|
|
||||||
# login url
|
# login url
|
||||||
@ -39,6 +39,9 @@ LOGIN_REDIRECT_URL = '/'
|
|||||||
LOGOUT_REDIRECT_URL = '/auth/login/'
|
LOGOUT_REDIRECT_URL = '/auth/login/'
|
||||||
|
|
||||||
|
|
||||||
|
# user profile
|
||||||
|
AUTH_PROFILE_MODULE = 'user_profile.Profile'
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
@ -82,6 +85,7 @@ TEMPLATES = [
|
|||||||
'django.template.context_processors.request',
|
'django.template.context_processors.request',
|
||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
'django.contrib.messages.context_processors.messages',
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
'django_settings_export.settings_export',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -153,3 +157,20 @@ STATICFILES_DIRS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
|
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||||
|
|
||||||
|
# Host for sending e-mail.
|
||||||
|
EMAIL_HOST = 'localhost'
|
||||||
|
|
||||||
|
# Port for sending e-mail.
|
||||||
|
EMAIL_PORT = 25
|
||||||
|
|
||||||
|
# Optional SMTP authentication information for EMAIL_HOST.
|
||||||
|
EMAIL_HOST_USER = ''
|
||||||
|
EMAIL_HOST_PASSWORD = ''
|
||||||
|
EMAIL_USE_TLS = False
|
||||||
|
DEFAULT_EMAIL_FROM = 'admin@dash-stack.org'
|
||||||
|
|
||||||
|
# fullt qualified hostname or domain. Ex <http://domain.tld/>
|
||||||
|
SITE_ROOT_URL = 'http://198.211.127.189/'
|
@ -3,3 +3,4 @@ Django==1.10.3
|
|||||||
mysqlclient==1.3.9
|
mysqlclient==1.3.9
|
||||||
oslo.i18n==3.10.0
|
oslo.i18n==3.10.0
|
||||||
requests==2.12.1
|
requests==2.12.1
|
||||||
|
django-settings-export==1.2.1
|
BIN
static/avatar/2016-12-10/aws_logo_web_300px.png
Normal file
BIN
static/avatar/2016-12-10/aws_logo_web_300px.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.0 KiB |
BIN
static/provider-logo/openstack-logo-1-300x150_soH1jUf.png
Normal file
BIN
static/provider-logo/openstack-logo-1-300x150_soH1jUf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
22
templates/authcp/activation.html
Normal file
22
templates/authcp/activation.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{% extends "base_headless.html" %}
|
||||||
|
|
||||||
|
{% block title %}<title>dash-stack | You have been activated </title>{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="register-box">
|
||||||
|
<div class="register-logo">
|
||||||
|
<a href="/"><b> - </b>stack</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="login-box-body">
|
||||||
|
<p class="lead">
|
||||||
|
Your email address has authanticated and
|
||||||
|
your user has been activated.
|
||||||
|
</p>
|
||||||
|
<a href="/" class="text-center">Let's go back to home page.</a><br />
|
||||||
|
<a href="/auth/login/" class="text-center">Take me to login page.</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
@ -1,8 +1,9 @@
|
|||||||
{% extends "base_headless.html" %}
|
{% extends "base_headless.html" %}
|
||||||
|
|
||||||
{% block auth %}
|
{% block title %}<title>dash-stack | Log in</title>{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
<body class="hold-transition login-page">
|
|
||||||
<div class="login-box">
|
<div class="login-box">
|
||||||
<div class="login-logo">
|
<div class="login-logo">
|
||||||
<a href="{{ SITE_URL }}"><b> - </b>stack</a>
|
<a href="{{ SITE_URL }}"><b> - </b>stack</a>
|
||||||
@ -12,11 +13,14 @@
|
|||||||
<p class="login-box-msg">Sign in to start your session</p>
|
<p class="login-box-msg">Sign in to start your session</p>
|
||||||
<form action="/auth/login/" method="POST">
|
<form action="/auth/login/" method="POST">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
<p class="text-red"> {{ form.non_field_errors.as_text }} </p>
|
||||||
<div class="form-group has-feedback">
|
<div class="form-group has-feedback">
|
||||||
|
<span class="text-red"> {{ form.errors.username.as_text }} </span>
|
||||||
<input type="email" name="username" class="form-control" placeholder="Email">
|
<input type="email" name="username" class="form-control" placeholder="Email">
|
||||||
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
|
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group has-feedback">
|
<div class="form-group has-feedback">
|
||||||
|
<span class="text-red"> {{ form.errors.password.as_text }} </span>
|
||||||
<input type="password" name="password" class="form-control" placeholder="Password">
|
<input type="password" name="password" class="form-control" placeholder="Password">
|
||||||
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
|
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
|
||||||
</div>
|
</div>
|
||||||
@ -24,7 +28,7 @@
|
|||||||
<div class="col-xs-8">
|
<div class="col-xs-8">
|
||||||
<div class="checkbox icheck">
|
<div class="checkbox icheck">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox"> Remember Me
|
<input name="remember_me" type="checkbox"> Remember Me
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -46,10 +50,10 @@
|
|||||||
<!-- /.social-auth-links -->
|
<!-- /.social-auth-links -->
|
||||||
|
|
||||||
<a href="#">I forgot my password</a><br>
|
<a href="#">I forgot my password</a><br>
|
||||||
<a href="register.html" class="text-center">Register a new membership</a>
|
<a href="/auth/register" class="text-center">Register a new membership</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.login-box-body -->
|
<!-- /.login-box-body -->
|
||||||
</div>
|
</div>
|
||||||
<!-- /.login-box -->
|
<!-- /.login-box -->
|
||||||
{% endblock auth %}
|
{% endblock content %}
|
62
templates/authcp/register.html
Normal file
62
templates/authcp/register.html
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{% extends "base_headless.html" %}
|
||||||
|
|
||||||
|
{% block title %}<title>dash-stack | Register </title>{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="register-box">
|
||||||
|
<div class="register-logo">
|
||||||
|
<a href="{{ SITE_URL }}"><b> - </b>stack</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="register-box-body">
|
||||||
|
<p class="login-box-msg">Register a new membership</p>
|
||||||
|
<form action="/auth/register/" method="POST">
|
||||||
|
<span class="text-red"> {{ form.errors.email.as_text }} </span>
|
||||||
|
<span class="text-red"> {{ form.errors.username.as_text }} </span>
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<input name="email" type="email" class="form-control" placeholder="Email">
|
||||||
|
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
|
||||||
|
</div>
|
||||||
|
<span class="text-red"> {{ form.errors.password1.as_text }} </span>
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<input name="password1" type="password" class="form-control" placeholder="Password">
|
||||||
|
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
|
||||||
|
</div>
|
||||||
|
<span class="text-red"> {{ form.errors.password2.as_text }} </span>
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<input name="password2" type="password" class="form-control" placeholder="Retype password">
|
||||||
|
<span class="glyphicon glyphicon-log-in form-control-feedback"></span>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<span class="text-red" style="margin-left: 15px;"> {{ form.errors.tos.as_text }} </span>
|
||||||
|
<div class="col-xs-8">
|
||||||
|
<div class="checkbox icheck">
|
||||||
|
<label>
|
||||||
|
<input name="tos" type="checkbox"> I agree to the <a href="#">terms</a>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.col -->
|
||||||
|
<div class="col-xs-4">
|
||||||
|
<button type="submit" class="btn btn-primary btn-block btn-flat">Register</button>
|
||||||
|
</div>
|
||||||
|
<!-- /.col -->
|
||||||
|
</div>
|
||||||
|
{% csrf_token %}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="social-auth-links text-center">
|
||||||
|
<p>- OR -</p>
|
||||||
|
<a href="#" class="btn btn-block btn-social btn-facebook btn-flat"><i class="fa fa-facebook"></i> Sign up using
|
||||||
|
Facebook</a>
|
||||||
|
<a href="#" class="btn btn-block btn-social btn-google btn-flat"><i class="fa fa-google-plus"></i> Sign up using
|
||||||
|
Google+</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="/auth/login" class="text-center">I already have a membership</a>
|
||||||
|
</div>
|
||||||
|
<!-- /.form-box -->
|
||||||
|
</div>
|
||||||
|
<!-- /.register-box -->
|
||||||
|
{% endblock content %}
|
25
templates/authcp/success.html
Normal file
25
templates/authcp/success.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{% extends "base_headless.html" %}
|
||||||
|
|
||||||
|
{% block title %}<title>dash-stack | Register </title>{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="register-box">
|
||||||
|
<div class="register-logo">
|
||||||
|
<a href="/"><b> - </b>stack</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ u.get_profile.activation_key }} <br>
|
||||||
|
{{ profile }}
|
||||||
|
|
||||||
|
<div class="login-box-body">
|
||||||
|
<p class="lead">
|
||||||
|
Thank you for registering a new account with us.
|
||||||
|
Please check your email for information.
|
||||||
|
</p>
|
||||||
|
<a href="/" class="text-center">Let's go back to home page.</a><br />
|
||||||
|
<a href="/auth/login/" class="text-center">Take me to login page.</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<title>AdminLTE 2 | Log in</title>
|
{% block title %}<title>AdminLTE 2 | Log in</title>{% endblock title %}
|
||||||
<!-- Tell the browser to be responsive to screen width -->
|
<!-- Tell the browser to be responsive to screen width -->
|
||||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
||||||
<!-- Bootstrap 3.3.6 -->
|
<!-- Bootstrap 3.3.6 -->
|
||||||
@ -24,9 +24,10 @@
|
|||||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
</head>
|
</head>
|
||||||
{% block auth %}
|
<body class="hold-transition login-page">
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
{% endblock auth %}
|
{% endblock content %}
|
||||||
|
|
||||||
<!-- jQuery 2.2.3 -->
|
<!-- jQuery 2.2.3 -->
|
||||||
<script src="/static/AdminLTE/plugins/jQuery/jquery-2.2.3.min.js"></script>
|
<script src="/static/AdminLTE/plugins/jQuery/jquery-2.2.3.min.js"></script>
|
||||||
|
20
templates/mail/user_register_welcome.html
Normal file
20
templates/mail/user_register_welcome.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<p>Hello,</p>
|
||||||
|
|
||||||
|
<p>Welcome to our cloud platform.</p>
|
||||||
|
|
||||||
|
<h3>Activate your email:</h3>
|
||||||
|
|
||||||
|
Please click on following link to activate your account:
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="{{ settings.SITE_ROOT_URL }}{{ profile.activation_key }}">
|
||||||
|
{{ profile.activation_key }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
6
templates/mail/user_register_welcome.txt
Normal file
6
templates/mail/user_register_welcome.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Hello,
|
||||||
|
|
||||||
|
Welcome to our cloud platform.
|
||||||
|
|
||||||
|
Activare your email:
|
||||||
|
|
27
user_profile/migrations/0003_auto_20161209_2125.py
Normal file
27
user_profile/migrations/0003_auto_20161209_2125.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.3 on 2016-12-09 21:25
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('user_profile', '0002_auto_20161201_2120'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='profile',
|
||||||
|
name='activation_key',
|
||||||
|
field=models.CharField(default='', max_length=64),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='profile',
|
||||||
|
name='key_expires',
|
||||||
|
field=models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
22
user_profile/migrations/0004_auto_20161210_1857.py
Normal file
22
user_profile/migrations/0004_auto_20161210_1857.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.3 on 2016-12-10 18:57
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('user_profile', '0003_auto_20161209_2125'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='user',
|
||||||
|
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
48
user_profile/migrations/0005_auto_20161210_1914.py
Normal file
48
user_profile/migrations/0005_auto_20161210_1914.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.3 on 2016-12-10 19:14
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('user_profile', '0004_auto_20161210_1857'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='profile',
|
||||||
|
options={'ordering': ('user',), 'verbose_name': 'Profile', 'verbose_name_plural': 'Profiles'},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='activation_key',
|
||||||
|
field=models.CharField(max_length=64, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='key_expires',
|
||||||
|
field=models.DateTimeField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='provider_password',
|
||||||
|
field=models.CharField(max_length=50, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='selected_provider',
|
||||||
|
field=models.IntegerField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='user',
|
||||||
|
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL, verbose_name='user'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
22
user_profile/migrations/0006_auto_20161210_1915.py
Normal file
22
user_profile/migrations/0006_auto_20161210_1915.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.3 on 2016-12-10 19:15
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('user_profile', '0005_auto_20161210_1914'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='key_expires',
|
||||||
|
field=models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
20
user_profile/migrations/0007_auto_20161210_1916.py
Normal file
20
user_profile/migrations/0007_auto_20161210_1916.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.3 on 2016-12-10 19:16
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('user_profile', '0006_auto_20161210_1915'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='key_expires',
|
||||||
|
field=models.DateTimeField(null=True),
|
||||||
|
),
|
||||||
|
]
|
22
user_profile/migrations/0008_auto_20161210_1917.py
Normal file
22
user_profile/migrations/0008_auto_20161210_1917.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.3 on 2016-12-10 19:17
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('user_profile', '0007_auto_20161210_1916'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='profile',
|
||||||
|
name='user',
|
||||||
|
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL, verbose_name='user'),
|
||||||
|
),
|
||||||
|
]
|
@ -1,14 +1,35 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User
|
from django.conf import settings
|
||||||
|
from django.dispatch import receiver
|
||||||
|
from django.db.models.signals import post_save
|
||||||
|
|
||||||
|
|
||||||
class Profile(models.Model):
|
class Profile(models.Model):
|
||||||
user = models.OneToOneField(
|
user = models.OneToOneField(
|
||||||
User,
|
settings.AUTH_USER_MODEL,
|
||||||
on_delete=models.CASCADE
|
related_name='profile',
|
||||||
|
verbose_name=('user'),
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
)
|
)
|
||||||
avatar = models.FileField(upload_to='static/avatar/%Y-%m-%d')
|
avatar = models.FileField(upload_to='static/avatar/%Y-%m-%d')
|
||||||
provider_password = models.CharField(max_length=50)
|
provider_password = models.CharField(max_length=50,null=True)
|
||||||
selected_provider = models.IntegerField()
|
selected_provider = models.IntegerField(null=True)
|
||||||
|
activation_key = models.CharField(max_length=64,null=True)
|
||||||
|
key_expires = models.DateTimeField(null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name=('Profile')
|
||||||
|
verbose_name_plural=('Profiles')
|
||||||
|
ordering=('user',)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.user.username
|
||||||
|
|
||||||
|
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
|
||||||
|
def create_profile_for_new_user(sender, created, instance, **kwargs):
|
||||||
|
if created:
|
||||||
|
profile = Profile(user=instance)
|
||||||
|
profile.save()
|
Loading…
x
Reference in New Issue
Block a user