├── README.md ├── oauth ├── __init__.py ├── admin.py ├── forms.py ├── migrations │ ├── __init__.py │ └── __init__.pyc ├── models.py ├── oauth_client.py ├── urls.py └── views.py └── templates ├── form.html └── message.html /README.md: -------------------------------------------------------------------------------- 1 | #django-oauth 2 |

3 | 项目说明 4 |

5 |

6 | 该项目是django的app应用,主要用途是使用OAuth2.0关联第三方账号。
7 |

8 |

9 | 鉴于我的django项目是采用django自带的用户认证系统,而且用户名是使用邮箱地址作为用户名。其中有些代码涉及到这两个东西,导致代码通用性一般。 10 |

11 |

12 | 推荐参考其中oauth/oauth_client.py文件即可。 13 |

14 |

15 | 也可以参考我博客:第三方登录整理 16 |

17 |

18 | 在我博客中,也对QQ、Sina、Github的OAuth开发过程中逐个写了博文: 19 |

20 |

21 | 1、QQ第三方登录 22 |

23 |

24 | 2、新浪微博第三方登录 25 |

26 |

27 | 3、Github第三方登录 28 |

29 |

30 | 目录说明 31 |

32 |

33 | oauth是实现oauth主要的代码,templates是相关的模版文件(根据自己情况需要修改) 34 |

35 |

36 | oauth相关设置记录在数据库中,即可以查看oauth/models.py中的OAuth_type设计。 37 |

38 |

39 | 使用说明 40 |

41 |

42 | 1、复制该应用到你的django项目中。 43 |

44 |

45 | 2、打开settings.py文件,INSTALLED_APP中添加应用 'oauth' 46 |

47 |

48 | 3、打开总的urls.py文件,添加本应用的路由设置 49 |

url(r'^oauth/',include('oauth.urls')),
50 |

51 |

52 | 4、更新数据库 53 |

54 |
python manage.py makemigrations
55 | python manage.py migrate
56 |

57 | 5、进入django后台管理,新增OAuth设置(包括回调地址、请求链接等等) 58 |

59 |

60 | 6、测试代码 --> 调试 --> 上线 61 |

-------------------------------------------------------------------------------- /oauth/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaddyYang/django-oauth/6a9347dfb4a15465b77e9c2575ae8a8b7db13976/oauth/__init__.py -------------------------------------------------------------------------------- /oauth/admin.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | from django.contrib import admin 3 | from .models import OAuth_type, OAuth_ex 4 | 5 | # Register your models here. 6 | class OAuthTypeAdmin(admin.ModelAdmin): 7 | list_display=('id','type_name', 'title', 'img') 8 | 9 | #分组表单 10 | fieldsets = ( 11 | (u'OAuth类型信息', { 12 | "fields":('type_name', 'title', 'img') 13 | }), 14 | (u'OAuth基本设置', { 15 | "fields":('client_id','client_secret','redirect_uri','scope') 16 | }), 17 | (u'OAuth请求链接', { 18 | "fields":('url_authorize','url_access_token','url_open_id','url_user_info','url_email') 19 | }) 20 | ) 21 | 22 | class OAuthAdmin(admin.ModelAdmin): 23 | list_display=('id', 'user', 'openid','oauth_type') 24 | 25 | admin.site.register(OAuth_ex, OAuthAdmin) 26 | admin.site.register(OAuth_type, OAuthTypeAdmin) 27 | -------------------------------------------------------------------------------- /oauth/forms.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | from django import forms 3 | from django.core.exceptions import ValidationError 4 | from django.contrib.auth.models import User 5 | from django.contrib.auth import authenticate 6 | 7 | from .models import OAuth_ex, OAuth_type 8 | 9 | class BindEmail(forms.Form): 10 | """bind the openid to email""" 11 | openid = forms.CharField(widget=forms.HiddenInput(attrs={'id':'openid'})) 12 | nickname = forms.CharField(widget=forms.HiddenInput(attrs={'id':'nickname'})) 13 | oauth_type_id = forms.CharField(widget=forms.HiddenInput(attrs={'id':'oauth_type'})) 14 | 15 | email = forms.EmailField(label=u'注册邮箱', 16 | widget=forms.EmailInput(attrs={'class':'form-control', 'id':'email','placeholder':u'请输入您注册用的邮箱'})) 17 | pwd = forms.CharField(label=u'用户密码', max_length=36, 18 | widget=forms.PasswordInput(attrs={'class':'form-control', 'id':'pwd','placeholder':u'若尚未注册过,该密码则作为用户密码'})) 19 | 20 | #验证邮箱 21 | def clean_email(self): 22 | oauth_type_id = self.cleaned_data.get('oauth_type_id') 23 | email = self.cleaned_data.get('email') 24 | 25 | users = User.objects.filter(email = email) 26 | oauth_type = OAuth_type.objects.get(id = oauth_type_id) 27 | 28 | if users: 29 | #判断是否被绑定了 30 | if OAuth_ex.objects.filter(user = users[0], oauth_type = oauth_type): 31 | raise ValidationError(u'该邮箱已经被绑定了') 32 | return email 33 | 34 | #验证密码 35 | def clean_pwd(self): 36 | email = self.cleaned_data.get('email') 37 | pwd = self.cleaned_data.get('pwd') 38 | 39 | users = User.objects.filter(email = email) 40 | if users: 41 | #若用户存在,判断密码是否正确 42 | user = authenticate(username=email, password=pwd) 43 | if user is not None: 44 | return pwd 45 | else: 46 | return ValidationError(u'密码不正确,不能绑定') 47 | -------------------------------------------------------------------------------- /oauth/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaddyYang/django-oauth/6a9347dfb4a15465b77e9c2575ae8a8b7db13976/oauth/migrations/__init__.py -------------------------------------------------------------------------------- /oauth/migrations/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaddyYang/django-oauth/6a9347dfb4a15465b77e9c2575ae8a8b7db13976/oauth/migrations/__init__.pyc -------------------------------------------------------------------------------- /oauth/models.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | from django.db import models 3 | 4 | #若不是使用系统的用户认证,可以换成你自己的用户系统 5 | from django.contrib.auth.models import User 6 | 7 | class OAuth_type(models.Model): 8 | """OAuth类型""" 9 | type_name = models.CharField(max_length = 12) 10 | title = models.CharField(max_length = 12) 11 | #图片上传的路径可以修改成自己的 12 | img = models.FileField(upload_to='static/img/connect') 13 | 14 | #oauth基本设置 15 | client_id = models.CharField(max_length = 24, default='') 16 | client_secret = models.CharField(max_length = 48, default='') 17 | redirect_uri = models.URLField(default='') 18 | scope = models.CharField(max_length = 24, default='') 19 | 20 | #oauth请求链接 21 | url_authorize = models.URLField(default='', blank=True) 22 | url_access_token = models.URLField(default='', blank=True) 23 | url_open_id = models.URLField(default='', blank=True) 24 | url_user_info = models.URLField(default='', blank=True) 25 | url_email = models.URLField(default='', blank=True) 26 | 27 | def __unicode__(self): 28 | return self.type_name 29 | 30 | class OAuth_ex(models.Model): 31 | """User用户绑定""" 32 | user = models.ForeignKey(User) #和User关联的外键 33 | openid = models.CharField(max_length = 64) 34 | oauth_type = models.ForeignKey(OAuth_type, default=1) #关联账号的类型 35 | 36 | def __unicode__(self): 37 | return u'<%s>' % (self.user) 38 | -------------------------------------------------------------------------------- /oauth/oauth_client.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import json 3 | import urllib, urllib2, urlparse 4 | import re 5 | 6 | class OAuth_Base(): 7 | def __init__(self, kw): 8 | if not isinstance(kw, dict): 9 | raise Exception("arg is not dict type") 10 | 11 | for key, value in kw.items(): 12 | setattr(self, key, value) 13 | 14 | @staticmethod 15 | def Get_OAth(**kw): 16 | """静态方法,根据参数实例化对应的类""" 17 | type_name = kw.get('type_name') 18 | 19 | if type_name == "QQ": 20 | oauth = OAuth_QQ(kw) 21 | elif type_name == "Sina": 22 | oauth = OAuth_Sina(kw) 23 | elif type_name == "Github": 24 | oauth = OAuth_Github(kw) 25 | else: 26 | oauth = None 27 | return oauth 28 | 29 | def _get(self, url, data): 30 | """get请求""" 31 | request_url = '%s?%s' % (url, urllib.urlencode(data)) 32 | response = urllib2.urlopen(request_url) 33 | return response.read() 34 | 35 | def _post(self, url, data): 36 | """post请求""" 37 | request = urllib2.Request(url, data = urllib.urlencode(data)) 38 | response = urllib2.urlopen(request) 39 | return response.read() 40 | 41 | #根据情况重写以下方法 42 | def get_auth_url(self): 43 | """获取授权页面的网址""" 44 | params = {'client_id': self.client_id, 45 | 'response_type': 'code', 46 | 'redirect_uri': self.redirect_uri, 47 | 'scope': self.scope, 48 | 'state': self.state} 49 | return '%s?%s' % (self.url_authorize, urllib.urlencode(params)) 50 | 51 | #继承的类要实现下面的方法 52 | def get_access_token(self, code): 53 | """根据code获取access_token""" 54 | pass 55 | 56 | def get_open_id(self): 57 | """获取用户的标识ID""" 58 | pass 59 | 60 | def get_user_info(self): 61 | """获取用户资料信息""" 62 | pass 63 | 64 | def get_email(self): 65 | """获取邮箱""" 66 | pass 67 | 68 | class OAuth_QQ(OAuth_Base): 69 | def get_access_token(self, code): 70 | """根据code获取access_token""" 71 | params = {'grant_type': 'authorization_code', 72 | 'client_id': self.client_id, 73 | 'client_secret': self.client_secret, 74 | 'code': code, 75 | 'redirect_uri': self.redirect_uri} 76 | response = self._get(self.url_access_token, params) 77 | 78 | #解析结果 79 | if response[:8] == 'callback': 80 | v_str = str(response)[9:-3] #去掉callback的字符 81 | v_json = json.loads(v_str) 82 | raise Exception(v_json['error_description']) 83 | else: 84 | result = urlparse.parse_qs(response, True) 85 | self.access_token = str(result['access_token'][0]) 86 | return self.access_token 87 | 88 | def get_open_id(self): 89 | """获取QQ的OpenID""" 90 | params = {'access_token': self.access_token} 91 | response = self._get(self.url_open_id, params) 92 | 93 | #去掉callback的字符 94 | result = json.loads(str(response)[9:-3] ) 95 | self.openid = result['openid'] 96 | return self.openid 97 | 98 | def get_user_info(self): 99 | """获取QQ用户的资料信息""" 100 | params = {'access_token': self.access_token, 101 | 'oauth_consumer_key': self.client_id, 102 | 'openid': self.openid} 103 | response = self._get(self.url_user_info, params) 104 | return json.loads(response) 105 | 106 | def get_email(self): 107 | """获取邮箱""" 108 | #QQ没有提供获取邮箱的方法 109 | raise Exception('can not get email') 110 | 111 | class OAuth_Sina(OAuth_Base): 112 | def get_access_token(self, code): 113 | """根据code获取access_token""" 114 | params = {'grant_type': 'authorization_code', 115 | 'client_id': self.client_id, 116 | 'client_secret': self.client_secret, 117 | 'code': code, 118 | 'redirect_uri': self.redirect_uri} 119 | 120 | #新浪微博此处是POST请求,返回JSON 121 | response = self._post(self.url_access_token, params) 122 | result = json.loads(response) 123 | 124 | self.access_token = result["access_token"] 125 | self.openid = result['uid'] 126 | return self.access_token 127 | 128 | def get_open_id(self): 129 | """获取Sina的uid,由于登录时就获取了,直接返回即可""" 130 | return self.openid 131 | 132 | def get_user_info(self): 133 | """获取用户资料信息""" 134 | params = {'access_token': self.access_token, 135 | 'uid': self.openid} 136 | response = self._get(self.url_user_info, params) 137 | return json.loads(response) 138 | 139 | def get_email(self): 140 | """获取邮箱""" 141 | #高级接口,需要申请 142 | params = {"access_token": self.access_token} 143 | response = self._get(self.url_email, params) 144 | #return response 145 | 146 | #分析结果,获取邮箱成功返回是一个字典数组,而不成功则是一个字典 147 | result = json.loads(response) 148 | 149 | #判断返回数据的类型 150 | if isinstance(result, list): 151 | #获取并判断邮箱格式是否正确 152 | email = result[0].get('email') 153 | pattern = re.compile(r'^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$') 154 | match = pattern.match(email) 155 | 156 | if not match: 157 | raise Exception(u"email format error") 158 | return email 159 | 160 | elif isinstance(result, dict): 161 | raise Exception(result.get('error', 'get email happened error')) 162 | else: 163 | raise Exception('get email api error') 164 | 165 | class OAuth_Github(OAuth_Base): 166 | openid = '' 167 | 168 | def get_access_token(self, code): 169 | params = {'grant_type': 'authorization_code', 170 | 'client_id': self.client_id, 171 | 'client_secret': self.client_secret, 172 | 'code': code, 173 | 'redirect_uri': self.redirect_uri} 174 | 175 | #Github此处是POST请求 176 | response = self._post(self.url_access_token, params) 177 | 178 | #解析结果 179 | result = urlparse.parse_qs(response, True) 180 | self.access_token = result['access_token'][0] 181 | return self.access_token 182 | 183 | def get_open_id(self): 184 | """获取用户的标识ID""" 185 | if not self.openid: 186 | #若没有openid,则调用一下获取用户信息的方法 187 | self.get_user_info() 188 | 189 | return self.openid 190 | 191 | def get_user_info(self): 192 | """获取用户资料信息""" 193 | params = {'access_token': self.access_token,} 194 | response = self._get(self.url_user_info, params) 195 | 196 | result = json.loads(response) 197 | self.openid = result.get('id', '') 198 | return result 199 | 200 | def get_email(self): 201 | """获取邮箱""" 202 | params = {'access_token': self.access_token,} 203 | response = self._get(self.url_email, params) 204 | 205 | result = json.loads(response) 206 | return result[0]['email'] 207 | -------------------------------------------------------------------------------- /oauth/urls.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | from django.conf.urls import include, url 3 | from .views as oauth_views 4 | 5 | #http://localhost:8000/oauth/ 6 | #start with 'oauth/' 7 | urlpatterns = [ 8 | url(r'^oauth_login/(?P[a-zA-Z]+)$', oauth_views.oauth_login, name='oauth_login'), 9 | 10 | #此处要和第三方账号填写的回调地址对应 11 | url(r'^qq_check$', oauth_views.qq_check, name='qq_check'), 12 | url(r'^sina_check$', oauth_views.sina_check, name='sina_check'), 13 | url(r'^github_check$', oauth_views.github_check, name='github_check'), 14 | 15 | url(r'^bind_email$', oauth_views.bind_email, name='bind_email'), 16 | ] 17 | -------------------------------------------------------------------------------- /oauth/views.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | from django.http import HttpResponseRedirect, Http404 3 | from django.shortcuts import render_to_response, render 4 | from django.core.urlresolvers import reverse #url逆向解析 5 | 6 | from django.contrib.auth.models import User 7 | from django.contrib.auth import authenticate, login 8 | from django.forms.models import model_to_dict #模型对象转字典 9 | 10 | from .oauth_client import OAuth_Base 11 | from .models import OAuth_ex, OAuth_type 12 | from .forms import BindEmail 13 | 14 | import time 15 | import uuid 16 | 17 | def _get_oauth(type_name, state): 18 | """获取对应的OAuth对象""" 19 | try: 20 | oauth_type = OAuth_type.objects.get(type_name = type_name) 21 | except: 22 | raise Http404 23 | 24 | kw = model_to_dict(oauth_type) 25 | kw['state'] = state 26 | return OAuth_Base.Get_OAth(**kw) 27 | 28 | def _login_error_response(message, jump_url): 29 | """登录出错跳转页面""" 30 | data = {} 31 | data['message'] = u'登录出错,请稍后重试
(辅助信息:%s)”' % (message or u"无") 32 | data['goto_url'] = jump_url 33 | data['goto_time'] = 3000 34 | data['goto_page'] = True 35 | return render_to_response('message.html', data) 36 | 37 | def _bind_email_response(open_id, nickname, type_name, jump_url): 38 | """绑定邮箱页面""" 39 | url = '%s?open_id=%s&nickname=%s&oauth_type=%s&state=%s' % (reverse('bind_email'), open_id, nickname, type_name, jump_url) 40 | return HttpResponseRedirect(url) 41 | 42 | def _bind_success_response(jump_url): 43 | """绑定并登录成功跳转页面""" 44 | data = {} 45 | data['goto_url'] = jump_url 46 | data['goto_time'] = 3000 47 | data['goto_page'] = True 48 | data['message'] = u'登录并绑定成功' 49 | return render_to_response('message.html', data) 50 | 51 | def _get_account_from_email(oauth_id, email, open_id, nickname): 52 | """通过邮箱获取用户""" 53 | #判断是否存在对应的用户(我这里的用户名就是邮箱,根据你的实际情况参考) 54 | users = User.objects.filter(username = email) 55 | 56 | if users: 57 | #存在则绑定和登录 58 | user = users[0] 59 | else: 60 | #不存在则直接注册并登录 61 | user = User(username = email, email = email) 62 | pwd = str(uuid.uuid1()) #生成随机密码 63 | user.set_password(pwd) 64 | user.is_active = True #真实邮箱来源,则认为是有效用户 65 | user.save() 66 | 67 | #添加绑定记录 68 | oauth_type = OAuth_type.objects.get(id = oauth_id) 69 | oauth_ex = OAuth_ex(user = user, openid = open_id, oauth_type = oauth_type) 70 | oauth_ex.save() 71 | 72 | #更新昵称 73 | if not user.first_name: 74 | user.first_name = nickname 75 | user.save() 76 | return user 77 | 78 | def _login_user(request, user): 79 | """直接登录用户""" 80 | #设置backend,绕开authenticate验证 81 | setattr(user, 'backend', 'django.contrib.auth.backends.ModelBackend') 82 | login(request, user) 83 | 84 | 85 | def oauth_login(request, type_name): 86 | #获取oauth对象 87 | state = request.GET.get('state') #获取登录页面记录的上一个网页网址信息 88 | oauth = _get_oauth(type_name, state) 89 | 90 | #获取 得到Authorization Code的地址 91 | url = oauth.get_auth_url() 92 | return HttpResponseRedirect(url) 93 | 94 | def qq_check(request): 95 | """登录之后,会跳转到这里。需要判断code和state""" 96 | request_code = request.GET.get('code') 97 | state = request.GET.get('state') or '/' 98 | oauth = _get_oauth('QQ', state) 99 | 100 | try: 101 | #获取access_token 102 | access_token = oauth.get_access_token(request_code) 103 | 104 | #稍微休息一下,避免发送urlopen的10060错误 105 | time.sleep(0.05) 106 | open_id = oauth.get_open_id() 107 | except Exception as e: 108 | #登录出错跳转到错误提示页面 109 | return _login_error_response(e.message, state) 110 | 111 | #检查open_id是否存在 112 | qqs = OAuth_ex.objects.filter(openid = open_id, oauth_type = oauth.id) 113 | if qqs: 114 | #存在则获取对应的用户,并登录 115 | _login_user(request, qqs[0].user) 116 | return HttpResponseRedirect(state) #跳转前验证这个网址? 117 | else: 118 | #不存在,则跳转到绑定邮箱页面 119 | infos = oauth.get_user_info() #获取用户信息 120 | nickname = infos['nickname'] 121 | return _bind_email_response(open_id, nickname, oauth.type_name, state) 122 | 123 | def sina_check(request): 124 | """登录之后,会跳转到这里。需要判断code和state""" 125 | request_code = request.GET.get('code') 126 | state = request.GET.get('state') or '/' 127 | oauth = _get_oauth('Sina', state) 128 | 129 | #获取access_token 130 | try: 131 | access_token = oauth.get_access_token(request_code) 132 | time.sleep(0.05) #稍微休息一下,避免发送urlopen的10060错误 133 | open_id = oauth.get_open_id() 134 | except Exception as e: 135 | #登录出错跳转到错误提示页面 136 | return _login_error_response(e.message, state) 137 | 138 | #检查uid是否存在 139 | sinas = OAuth_ex.objects.filter(openid = open_id, oauth_type = oauth.id) 140 | if sinas: 141 | #存在则获取对应的用户,并登录 142 | _login_user(request, sinas[0].user) 143 | return HttpResponseRedirect(state) 144 | else: 145 | #不存在,则尝试获取邮箱 146 | try: 147 | #获取得到邮箱则直接绑定 148 | email = oauth.get_email() 149 | except Exception as e: 150 | #获取不到则跳转到邮箱绑定页面 151 | #获取用户资料 152 | infos = oauth.get_user_info() 153 | nickname = infos['screen_name'] 154 | return _bind_email_response(open_id, nickname, oauth.type_name, state) 155 | 156 | #获取到邮箱,直接绑定 157 | #判断是否存在对应的用户(我这里的用户名就是邮箱,根据你的实际情况参考) 158 | user = _get_account_from_email(oauth.id, email, open_id, nickname) 159 | 160 | #登录并跳转 161 | _login_user(request, user) 162 | return _bind_success_response(state) 163 | 164 | def github_check(request): 165 | """登录之后,会跳转到这里。需要判断code和state""" 166 | request_code = request.GET.get('code') 167 | state = request.GET.get('state') or '/' 168 | oauth = _get_oauth('Github', state) 169 | 170 | #获取access_token 171 | try: 172 | access_token = oauth.get_access_token(request_code) 173 | time.sleep(0.05) #稍微休息一下,避免发送urlopen的10060错误 174 | except Exception as e: 175 | #登录出错跳转到错误提示页面 176 | return _login_error_response(e.message, state) 177 | 178 | #获取用户信息 179 | infos = oauth.get_user_info() 180 | open_id = str(infos.get('id', '')) 181 | nickname = infos.get('login', '') 182 | 183 | #检查id是否存在 184 | githubs = OAuth_ex.objects.filter(openid = open_id, oauth_type = oauth.id) 185 | 186 | #获取邮箱 187 | if githubs: 188 | #存在则获取对应的用户,并登录 189 | _login_user(request, githubs[0].user) 190 | return HttpResponseRedirect(state) 191 | else: 192 | #不存在,则尝试获取邮箱 193 | try: 194 | #获取得到邮箱则直接绑定 195 | email = oauth.get_email() 196 | except Exception as e: 197 | #获取不到即跳转到绑定用户 198 | return _bind_email_response(open_id, nickname, oauth.type_name, state) 199 | 200 | #获取到邮箱,直接绑定 201 | #判断是否存在对应的用户(我这里的用户名就是邮箱,根据你的实际情况参考) 202 | user = _get_account_from_email(oauth.id, email, open_id, nickname) 203 | 204 | #登录并跳转 205 | _login_user(request, user) 206 | return _bind_success_response(state) 207 | 208 | def bind_email(request): 209 | open_id = request.GET.get('open_id') 210 | nickname = request.GET.get('nickname') 211 | oauth_type = request.GET.get('oauth_type') 212 | state = request.GET.get('state') or '/' 213 | data = {} 214 | 215 | #判断oauth类型 216 | oauth_types = OAuth_type.objects.filter(type_name = oauth_type) 217 | if oauth_types.count() > 0: 218 | oauth_type = oauth_types[0] 219 | img_url = oauth_type.img 220 | else: 221 | data['goto_url'] = state 222 | data['goto_time'] = 3000 223 | data['goto_page'] = True 224 | data['message'] = u'错误的登录类型,请检查' 225 | return render_to_response('message.html',data) 226 | 227 | data['form_title'] = u'绑定用户' 228 | data['submit_name'] = u' 确定 ' 229 | data['form_tip'] = u'Hi, %s!您已登录。请绑定用户,完成登录' % (img_url, nickname) 230 | 231 | if request.method == 'POST': 232 | #表单提交 233 | form = BindEmail(request.POST) 234 | 235 | #验证是否合法 236 | if form.is_valid(): 237 | #判断邮箱是否注册了 238 | openid = form.cleaned_data['openid'] 239 | nickname = form.cleaned_data['nickname'] 240 | email = form.cleaned_data['email'] 241 | pwd = form.cleaned_data['pwd'] 242 | 243 | users = User.objects.filter(email = email) 244 | if users: 245 | #用户存在,则直接绑定 246 | user = users[0] 247 | if not user.first_name: 248 | user.first_name = nickname #更新昵称 249 | user.save() 250 | data['message'] = u'绑定账号成功,绑定到%s”' % email 251 | else: 252 | #用户不存在,则注册,并发送激活邮件 253 | user=User(username=email, email=email) 254 | user.first_name = nickname #使用第三方账号昵称作为昵称 255 | user.set_password(pwd) 256 | user.is_active=True #激活,此处也可以不用先激活。发送一个邮件确认用户身份,再激活 257 | user.save() 258 | 259 | data['message'] = u'绑定账号成功' 260 | 261 | #绑定用户 262 | oauth_ex = OAuth_ex(user = user, openid = openid, oauth_type = oauth_type) 263 | oauth_ex.save() 264 | 265 | #登录用户 266 | user = authenticate(username=email, password=pwd) 267 | if user is not None: 268 | login(request, user) 269 | 270 | #页面提示 271 | data['goto_url'] = state 272 | data['goto_time'] = 3000 273 | data['goto_page'] = True 274 | 275 | return render_to_response('message.html',data) 276 | else: 277 | #正常加载 278 | form = BindEmail(initial={ 279 | 'openid': open_id, 280 | 'nickname': nickname, 281 | 'oauth_type_id': oauth_type.id, 282 | }) 283 | data['form'] = form 284 | return render(request, 'form.html', data) 285 | -------------------------------------------------------------------------------- /templates/form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}杨仕航的博客{% endblock %} 4 | 5 | {% block content %} 6 | {#通用表单页面#} 7 |
8 |
9 |
10 |
11 |

{{form_title}}

12 |

{{form_tip|safe}}

13 |
14 | {%csrf_token%} 15 | {% for field in form %} 16 | {# 区分是否是hidden字段 #} 17 | {% if field.is_hidden %} 18 | {{ field }} 19 | {% else %} 20 |
21 | 24 | {{ field }} 25 |
26 | {# 错误提示信息 #} 27 |

28 | {{ field.errors.as_text }} 29 |

30 | {%endif%} 31 | {%endfor%} 32 | 33 |
34 | 35 |
36 |
37 |
38 |
39 |
40 |
41 | {% endblock %} 42 | 43 | {% block extra_footer %} 44 | 58 | {% endblock %} 59 | -------------------------------------------------------------------------------- /templates/message.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}杨仕航的博客{% endblock %} 4 | 5 | {% block content %} 6 | {#显示消息的页面#} 7 |
8 |

{{message|safe}}

9 |
10 | {% endblock %} 11 | 12 | {% block extra_footer %} 13 | 23 | {% endblock %} --------------------------------------------------------------------------------