Commit c323519dd4538463109e4b588e0f727fb269575a
1 parent
b6c4f3cc38
Exists in
de
m
Showing
6 changed files
with
264 additions
and
14 deletions
Show diff stats
decrators.py
File was created | 1 | # coding: utf-8 | |
2 | |||
3 | import django.http | ||
4 | from functools import wraps | ||
5 | from django.conf import settings | ||
6 | from django.utils.decorators import available_attrs | ||
7 | from django.shortcuts import resolve_url | ||
8 | from django.utils.six.moves.urllib.parse import urlparse | ||
9 | |||
10 | def weapp_django_logout(request, response): | ||
11 | assert isinstance(request, django.http.HttpRequest) | ||
12 | assert isinstance(response, django.http.HttpResponse) | ||
13 | # 请求统一认证登出 | ||
14 | response.delete_cookie('pt') | ||
15 | response.delete_cookie('pu') | ||
16 | response.delete_cookie('username') | ||
17 | return response | ||
18 | |||
19 | def weapp_logout(func=weapp_django_logout): | ||
20 | """ | ||
21 | Django登出视图函数装饰器 | ||
22 | :param func: 处理登出逻辑的函数,接受request和response两个参数 | ||
23 | :return: | ||
24 | """ | ||
25 | return auth_decorator_factory(func) | ||
26 | |||
27 | |||
28 | def auth_decorator_factory(func=None): | ||
29 | """ | ||
30 | 登录登出装饰器工厂函数,允许用户自定义外部登录登出函数 | ||
31 | :param func: | ||
32 | :return: | ||
33 | """ | ||
34 | |||
35 | def decorator(view_func): | ||
36 | @wraps(view_func) | ||
37 | def _wrapped_view(request, *args, **kwargs): | ||
38 | response = view_func(request, *args, **kwargs) | ||
39 | if func: | ||
40 | func(request, response) | ||
41 | return response | ||
42 | |||
43 | return _wrapped_view | ||
44 | |||
45 | return decorator | ||
46 | |||
47 | import json | ||
48 | |||
49 | from django.http import JsonResponse | ||
50 | |||
51 | |||
52 | class QCCRJsonResponse(JsonResponse): | ||
53 | """ | ||
54 | 封装了返回码和信息的JsonResponse类 | ||
55 | """ | ||
56 | def __init__(self, obj=None, code=200, msg="success", status=200, **kwargs): | ||
57 | data = {"code": code, "msg": msg, "result": json.loads(obj) if isinstance(obj, (str, unicode)) else obj} | ||
58 | super(QCCRJsonResponse, self).__init__(data=data, status=status, **kwargs) | ||
59 | |||
60 | |||
61 | class QCCRErrorResponse(QCCRJsonResponse): | ||
62 | """ | ||
63 | 请求错误 | ||
64 | """ | ||
65 | def __init__(self, obj=None, code=400, msg="failure", status=400, **kwargs): | ||
66 | super(QCCRErrorResponse, self).__init__(obj=obj, code=code, msg=msg, status=status, **kwargs) | ||
67 | |||
68 | def user_passes_test(test_func, login_url=None, | ||
69 | redirect_field_name=getattr(settings, "QCCR_REDIRECT_FIELD_NAME", 'redirect')): | ||
70 | """ | ||
71 | 本装饰器通过test_func函数,检查views是否通过相应的检测,未通过则跳转到登录页面;test_func函数接受user对象作为参数,通过则返回True | ||
72 | """ | ||
73 | |||
74 | def decorator(view_func): | ||
75 | @wraps(view_func, assigned=available_attrs(view_func)) | ||
76 | def _wrapped_view(request, *args, **kwargs): | ||
77 | if test_func(request.user): | ||
78 | return view_func(request, *args, **kwargs) | ||
79 | # 如果未通过检查,且为ajax请求,返回403 | ||
80 | if request.is_ajax(): | ||
81 | return QCCRErrorResponse(code=403, msg="用户身份检查失败", status=403) | ||
82 | # 非ajax请求,跳转到登录页面 | ||
83 | path = request.build_absolute_uri() | ||
84 | resolved_login_url = resolve_url(login_url or getattr(settings, "QCCR_LOGIN_URL", '/login/')) | ||
85 | login_scheme, login_netloc = urlparse(resolved_login_url)[:2] | ||
86 | current_scheme, current_netloc = urlparse(path)[:2] | ||
87 | if ((not login_scheme or login_scheme == current_scheme) and | ||
88 | (not login_netloc or login_netloc == current_netloc)): | ||
89 | path = request.get_full_path() | ||
90 | from django.contrib.auth.views import redirect_to_login | ||
91 | return redirect_to_login(path, resolved_login_url, redirect_field_name) | ||
92 | |||
93 | return _wrapped_view | ||
94 | |||
95 | return decorator | ||
96 | |||
97 | |||
98 | def weapp_login_required(function=None, | ||
99 | redirect_field_name=getattr(settings, "QCCR_REDIRECT_FIELD_NAME", 'redirect'), | ||
100 | login_url=None): | ||
101 | """ | ||
102 | 登录状态检查装饰器,如果未登录,则直接跳转到登录页面 | ||
103 | """ | ||
104 | actual_decorator = user_passes_test( | ||
105 | lambda u: u.is_authenticated(), | ||
106 | login_url=login_url, | ||
107 | redirect_field_name=redirect_field_name | ||
108 | ) | ||
109 | if function: | ||
110 | return actual_decorator(function) | ||
111 | return actual_decorator |
forum/forms/user.py
1 | # coding: utf-8 | 1 | # coding: utf-8 |
2 | 2 | ||
3 | import requests | ||
3 | from django import forms | 4 | from django import forms |
4 | from django.contrib.auth import authenticate | 5 | from django.contrib.auth import authenticate |
5 | from django.conf import settings | 6 | from django.conf import settings |
6 | from forum.models import ForumUser | 7 | from forum.models import ForumUser |
7 | 8 | ||
8 | 9 | ||
9 | error_messages = { | 10 | error_messages = { |
10 | 'username': { | 11 | 'username': { |
11 | 'required': u'必须填写用户名', | 12 | 'required': u'必须填写用户名', |
12 | 'min_length': u'用户名长度过短(3-12个字符)', | 13 | 'min_length': u'用户名长度过短(3-12个字符)', |
13 | 'max_length': u'用户名长度过长(3-12个字符)', | 14 | 'max_length': u'用户名长度过长(3-12个字符)', |
14 | 'invalid': u'用户名格式错误(英文字母开头,数字,下划线构成)' | 15 | 'invalid': u'用户名格式错误(英文字母开头,数字,下划线构成)' |
15 | }, | 16 | }, |
16 | 'email': { | 17 | 'email': { |
17 | 'required': u'必须填写E-mail', | 18 | 'required': u'必须填写E-mail', |
18 | 'min_length': u'Email长度有误', | 19 | 'min_length': u'Email长度有误', |
19 | 'max_length': u'Email长度有误', | 20 | 'max_length': u'Email长度有误', |
20 | 'invalid': u'Email地址无效' | 21 | 'invalid': u'Email地址无效' |
21 | }, | 22 | }, |
22 | 'password': { | 23 | 'password': { |
23 | 'required': u'必须填写密码', | 24 | 'required': u'必须填写密码', |
24 | 'min_length': u'密码长度过短(6-64个字符)', | 25 | 'min_length': u'密码长度过短(6-64个字符)', |
25 | 'max_length': u'密码长度过长(6-64个字符)' | 26 | 'max_length': u'密码长度过长(6-64个字符)' |
26 | }, | 27 | }, |
27 | } | 28 | } |
28 | 29 | ||
29 | 30 | ||
30 | class SettingPasswordForm(forms.Form): | 31 | class SettingPasswordForm(forms.Form): |
31 | password_old = forms.CharField(min_length=6, max_length=64, | 32 | password_old = forms.CharField(min_length=6, max_length=64, |
32 | error_messages=error_messages.get('password')) | 33 | error_messages=error_messages.get('password')) |
33 | password = forms.CharField(min_length=6, max_length=64, | 34 | password = forms.CharField(min_length=6, max_length=64, |
34 | error_messages=error_messages.get('password')) | 35 | error_messages=error_messages.get('password')) |
35 | password_confirm = forms.CharField(required=False) | 36 | password_confirm = forms.CharField(required=False) |
36 | 37 | ||
37 | def __init__(self, request): | 38 | def __init__(self, request): |
38 | self.user = request.user | 39 | self.user = request.user |
39 | super(SettingPasswordForm, self).__init__(request.POST) | 40 | super(SettingPasswordForm, self).__init__(request.POST) |
40 | 41 | ||
41 | def clean(self): | 42 | def clean(self): |
42 | password_old = self.cleaned_data.get('password_old') | 43 | password_old = self.cleaned_data.get('password_old') |
43 | password = self.cleaned_data.get('password') | 44 | password = self.cleaned_data.get('password') |
44 | password_confirm = self.cleaned_data.get('password_confirm') | 45 | password_confirm = self.cleaned_data.get('password_confirm') |
45 | 46 | ||
46 | if not (password_old and self.user.check_password(password_old)): | 47 | if not (password_old and self.user.check_password(password_old)): |
47 | raise forms.ValidationError(u'当前输入旧密码有误') | 48 | raise forms.ValidationError(u'当前输入旧密码有误') |
48 | 49 | ||
49 | if password and password_confirm and password != password_confirm: | 50 | if password and password_confirm and password != password_confirm: |
50 | raise forms.ValidationError(u'两次输入新密码不一致') | 51 | raise forms.ValidationError(u'两次输入新密码不一致') |
51 | return self.cleaned_data | 52 | return self.cleaned_data |
52 | 53 | ||
53 | 54 | ||
54 | class ForgotPasswordForm(forms.Form): | 55 | class ForgotPasswordForm(forms.Form): |
55 | username = forms.RegexField(min_length=3, max_length=12, | 56 | username = forms.RegexField(min_length=3, max_length=12, |
56 | regex=r'^[a-zA-Z][a-zA-Z0-9_]*$', | 57 | regex=r'^[a-zA-Z][a-zA-Z0-9_]*$', |
57 | error_messages=error_messages.get('username')) | 58 | error_messages=error_messages.get('username')) |
58 | email = forms.EmailField(min_length=4, max_length=64, | 59 | email = forms.EmailField(min_length=4, max_length=64, |
59 | error_messages=error_messages.get('email')) | 60 | error_messages=error_messages.get('email')) |
60 | 61 | ||
61 | def __init__(self, *args, **kwargs): | 62 | def __init__(self, *args, **kwargs): |
62 | self.user_cache = None | 63 | self.user_cache = None |
63 | super(ForgotPasswordForm, self).__init__(*args, **kwargs) | 64 | super(ForgotPasswordForm, self).__init__(*args, **kwargs) |
64 | 65 | ||
65 | def clean(self): | 66 | def clean(self): |
66 | username = self.cleaned_data.get('username') | 67 | username = self.cleaned_data.get('username') |
67 | email = self.cleaned_data.get('email') | 68 | email = self.cleaned_data.get('email') |
68 | 69 | ||
69 | if username and email: | 70 | if username and email: |
70 | try: | 71 | try: |
71 | self.user_cache = ForumUser.objects.get(username=username, email=email) | 72 | self.user_cache = ForumUser.objects.get(username=username, email=email) |
72 | except ForumUser.DoesNotExist: | 73 | except ForumUser.DoesNotExist: |
73 | raise forms.ValidationError(u'所填用户名和邮箱有误') | 74 | raise forms.ValidationError(u'所填用户名和邮箱有误') |
74 | return self.cleaned_data | 75 | return self.cleaned_data |
75 | 76 | ||
76 | def get_user(self): | 77 | def get_user(self): |
77 | return self.user_cache | 78 | return self.user_cache |
78 | 79 | ||
79 | 80 | ||
80 | class LoginForm(forms.Form): | 81 | class LoginForm(forms.Form): |
81 | username = forms.CharField(min_length=3, max_length=12, | 82 | username = forms.CharField(min_length=3, max_length=12, |
82 | error_messages=error_messages.get('username')) | 83 | error_messages=error_messages.get('username')) |
83 | password = forms.CharField(min_length=6, max_length=64, | 84 | password = forms.CharField(min_length=6, max_length=64, |
84 | error_messages=error_messages.get('password')) | 85 | error_messages=error_messages.get('password')) |
85 | 86 | ||
86 | def __init__(self, *args, **kwargs): | 87 | def __init__(self, *args, **kwargs): |
87 | self.user_cache = None | 88 | self.user_cache = None |
89 | self.pu = '' | ||
90 | self.pt = '' | ||
91 | self.username = '' | ||
88 | super(LoginForm, self).__init__(*args, **kwargs) | 92 | super(LoginForm, self).__init__(*args, **kwargs) |
89 | 93 | ||
90 | def clean(self): | 94 | def clean(self): |
91 | username = self.cleaned_data.get('username') | 95 | username = self.cleaned_data.get('username') |
92 | password = self.cleaned_data.get('password') | 96 | password = self.cleaned_data.get('password') |
93 | 97 | ||
94 | if username and password: | 98 | if username and password: |
95 | self.user_cache = authenticate(username=username, password=password) | 99 | post_params = { |
96 | if self.user_cache is None: | 100 | 'comefrom': 2, |
97 | raise forms.ValidationError(u'用户名或者密码不正确') | 101 | 'user_name': username, |
98 | elif not self.user_cache.is_active: | 102 | 'password': password, |
99 | raise forms.ValidationError(u'用户已被锁定,请联系管理员解锁') | 103 | } |
104 | resp = requests.post(settings.AUTH_DOMAIN, data=post_params, verify=False) | ||
105 | if resp.status_code == 200: | ||
106 | rst = resp.json() | ||
107 | if rst.get('status') == 1: | ||
108 | data = rst.get('data') | ||
109 | self.pt = data.get('token') | ||
110 | self.pu = data.get('suid') | ||
111 | self.username = username | ||
112 | else: | ||
113 | raise forms.ValidationError(u'用户名或者密码不正确') | ||
114 | else: | ||
115 | raise forms.ValidationError(u'连接登录中心失败') | ||
116 | |||
100 | return self.cleaned_data | 117 | return self.cleaned_data |
101 | 118 | ||
102 | def get_user(self): | 119 | def get_user(self): |
103 | return self.user_cache | 120 | return { |
121 | 'pt': self.pt, | ||
122 | 'pu': self.pu, | ||
123 | 'username': self.username, | ||
124 | } | ||
104 | 125 | ||
105 | 126 | ||
106 | class RegisterForm(forms.ModelForm): | 127 | class RegisterForm(forms.ModelForm): |
107 | username = forms.RegexField(min_length=3, max_length=12, | 128 | username = forms.RegexField(min_length=3, max_length=12, |
108 | regex=r'^[a-zA-Z][a-zA-Z0-9_]*$', | 129 | regex=r'^[a-zA-Z][a-zA-Z0-9_]*$', |
109 | error_messages=error_messages.get('username')) | 130 | error_messages=error_messages.get('username')) |
110 | email = forms.EmailField(min_length=4, max_length=64, | 131 | email = forms.EmailField(min_length=4, max_length=64, |
111 | error_messages=error_messages.get('email')) | 132 | error_messages=error_messages.get('email')) |
112 | password = forms.CharField(min_length=6, max_length=64, | 133 | password = forms.CharField(min_length=6, max_length=64, |
113 | error_messages=error_messages.get('password')) | 134 | error_messages=error_messages.get('password')) |
114 | password_confirm = forms.CharField(required=False) | 135 | password_confirm = forms.CharField(required=False) |
115 | 136 | ||
116 | class Meta: | 137 | class Meta: |
117 | model = ForumUser | 138 | model = ForumUser |
118 | fields = ('username', 'email') | 139 | fields = ('username', 'email') |
119 | 140 | ||
120 | def clean_username(self): | 141 | def clean_username(self): |
121 | username = self.cleaned_data['username'] | 142 | username = self.cleaned_data['username'] |
122 | try: | 143 | try: |
123 | ForumUser.objects.get(username=username) | 144 | ForumUser.objects.get(username=username) |
124 | raise forms.ValidationError(u'所填用户名已经被注册过') | 145 | raise forms.ValidationError(u'所填用户名已经被注册过') |
125 | except ForumUser.DoesNotExist: | 146 | except ForumUser.DoesNotExist: |
126 | if username in settings.RESERVED: | 147 | if username in settings.RESERVED: |
127 | raise forms.ValidationError(u'用户名被保留不可用') | 148 | raise forms.ValidationError(u'用户名被保留不可用') |
128 | return username | 149 | return username |
129 | 150 | ||
130 | def clean_email(self): | 151 | def clean_email(self): |
131 | email = self.cleaned_data['email'] | 152 | email = self.cleaned_data['email'] |
132 | try: | 153 | try: |
133 | ForumUser.objects.get(email=email) | 154 | ForumUser.objects.get(email=email) |
134 | raise forms.ValidationError(u'所填邮箱已经被注册过') | 155 | raise forms.ValidationError(u'所填邮箱已经被注册过') |
135 | except ForumUser.DoesNotExist: | 156 | except ForumUser.DoesNotExist: |
136 | return email | 157 | return email |
137 | 158 | ||
138 | def clean_password_confirm(self): | 159 | def clean_password_confirm(self): |
139 | password1 = self.cleaned_data.get('password') | 160 | password1 = self.cleaned_data.get('password') |
140 | password2 = self.cleaned_data.get('password_confirm') | 161 | password2 = self.cleaned_data.get('password_confirm') |
141 | if password1 and password2 and password1 != password2: | 162 | if password1 and password2 and password1 != password2: |
142 | raise forms.ValidationError(u'两次输入密码不一致') | 163 | raise forms.ValidationError(u'两次输入密码不一致') |
143 | return password2 | 164 | return password2 |
144 | 165 | ||
145 | def save(self, commit=True): | 166 | def save(self, commit=True): |
146 | user = super(RegisterForm, self).save(commit=False) | 167 | user = super(RegisterForm, self).save(commit=False) |
147 | user.set_password(self.cleaned_data['password']) | 168 | user.set_password(self.cleaned_data['password']) |
148 | if commit: | 169 | if commit: |
149 | user.save() | 170 | user.save() |
150 | return user | 171 | return user |
151 | 172 | ||
152 | 173 | ||
153 | class SettingForm(forms.Form): | 174 | class SettingForm(forms.Form): |
154 | username = forms.CharField() # readonly | 175 | username = forms.CharField() # readonly |
155 | email = forms.EmailField() # readonly | 176 | email = forms.EmailField() # readonly |
156 | nickname = forms.CharField(min_length=3, max_length=12, required=False, | 177 | nickname = forms.CharField(min_length=3, max_length=12, required=False, |
157 | error_messages={ | 178 | error_messages={ |
158 | 'min_length': u'昵称长度过短(3-12个字符)', | 179 | 'min_length': u'昵称长度过短(3-12个字符)', |
159 | 'max_length': u'昵称长度过长(3-12个字符)', | 180 | 'max_length': u'昵称长度过长(3-12个字符)', |
160 | }) | 181 | }) |
161 | signature = forms.CharField(required=False) | 182 | signature = forms.CharField(required=False) |
162 | location = forms.CharField(required=False) | 183 | location = forms.CharField(required=False) |
163 | website = forms.URLField(required=False, | 184 | website = forms.URLField(required=False, |
164 | error_messages={ | 185 | error_messages={ |
165 | 'invalid': u'请填写合法的URL地址(如:http://f2e.im)', | 186 | 'invalid': u'请填写合法的URL地址(如:http://f2e.im)', |
166 | }) | 187 | }) |
167 | company = forms.CharField(required=False) | 188 | company = forms.CharField(required=False) |
168 | github = forms.CharField(required=False) | 189 | github = forms.CharField(required=False) |
169 | twitter = forms.CharField(required=False) | 190 | twitter = forms.CharField(required=False) |
170 | douban = forms.CharField(required=False) | 191 | douban = forms.CharField(required=False) |
171 | self_intro = forms.CharField(required=False) | 192 | self_intro = forms.CharField(required=False) |
172 | 193 |
forum/views/user.py
1 | # coding: utf-8 | 1 | # coding: utf-8 |
2 | 2 | ||
3 | import requests | ||
3 | import os, uuid, copy, urllib | 4 | import os, uuid, copy, urllib |
4 | from PIL import Image | 5 | from PIL import Image |
5 | from django.shortcuts import render_to_response, redirect | 6 | from django.shortcuts import render_to_response, redirect |
6 | from django.contrib import auth | 7 | from django.contrib import auth |
7 | from django.contrib.auth.decorators import login_required | 8 | from django.contrib.auth.decorators import login_required |
8 | from django.template import RequestContext, Context, loader | 9 | from django.template import RequestContext, Context, loader |
9 | from django.utils import timezone | 10 | from django.utils import timezone |
10 | from django.conf import settings | 11 | from django.conf import settings |
11 | from forum.models import ForumUser | 12 | from forum.models import ForumUser |
12 | from forum.forms.user import RegisterForm, LoginForm, ForgotPasswordForm, SettingPasswordForm, SettingForm | 13 | from forum.forms.user import RegisterForm, LoginForm, ForgotPasswordForm, SettingPasswordForm, SettingForm |
13 | from common import sendmail | 14 | from common import sendmail |
14 | 15 | ||
15 | 16 | ||
16 | @login_required | 17 | @login_required |
17 | def get_setting(request, **kwargs): | 18 | def get_setting(request, **kwargs): |
18 | return render_to_response('user/setting.html', kwargs, | 19 | return render_to_response('user/setting.html', kwargs, |
19 | context_instance=RequestContext(request)) | 20 | context_instance=RequestContext(request)) |
20 | 21 | ||
21 | 22 | ||
22 | @login_required | 23 | @login_required |
23 | def post_setting(request): | 24 | def post_setting(request): |
24 | form = SettingForm(request.POST) | 25 | form = SettingForm(request.POST) |
25 | if not form.is_valid(): | 26 | if not form.is_valid(): |
26 | return get_setting(request, errors=form.errors) | 27 | return get_setting(request, errors=form.errors) |
27 | 28 | ||
28 | user = request.user | 29 | user = request.user |
29 | cd = copy.copy(form.cleaned_data) | 30 | cd = copy.copy(form.cleaned_data) |
30 | cd.pop('username') | 31 | cd.pop('username') |
31 | cd.pop('email') | 32 | cd.pop('email') |
32 | for k, v in cd.iteritems(): | 33 | for k, v in cd.iteritems(): |
33 | setattr(user, k, v) | 34 | setattr(user, k, v) |
34 | user.updated = timezone.now() | 35 | user.updated = timezone.now() |
35 | user.save() | 36 | user.save() |
36 | return get_setting(request, success_message=u'用户基本资料更新成功') | 37 | return get_setting(request, success_message=u'用户基本资料更新成功') |
37 | 38 | ||
38 | 39 | ||
39 | @login_required | 40 | @login_required |
40 | def get_setting_avatar(request, **kwargs): | 41 | def get_setting_avatar(request, **kwargs): |
41 | return render_to_response('user/setting_avatar.html', kwargs, | 42 | return render_to_response('user/setting_avatar.html', kwargs, |
42 | context_instance=RequestContext(request)) | 43 | context_instance=RequestContext(request)) |
43 | 44 | ||
44 | 45 | ||
45 | @login_required | 46 | @login_required |
46 | def post_setting_avatar(request): | 47 | def post_setting_avatar(request): |
47 | if not 'avatar' in request.FILES: | 48 | if not 'avatar' in request.FILES: |
48 | errors = {'invalid_avatar': [u'请先选择要上传的头像'],} | 49 | errors = {'invalid_avatar': [u'请先选择要上传的头像'],} |
49 | return get_setting_avatar(request, errors=errors) | 50 | return get_setting_avatar(request, errors=errors) |
50 | 51 | ||
51 | user = request.user | 52 | user = request.user |
52 | avatar_name = '%s' % uuid.uuid5(uuid.NAMESPACE_DNS, str(user.id)) | 53 | avatar_name = '%s' % uuid.uuid5(uuid.NAMESPACE_DNS, str(user.id)) |
53 | avatar = Image.open(request.FILES['avatar']) | 54 | avatar = Image.open(request.FILES['avatar']) |
54 | 55 | ||
55 | # crop avatar if it's not square | 56 | # crop avatar if it's not square |
56 | avatar_w, avatar_h = avatar.size | 57 | avatar_w, avatar_h = avatar.size |
57 | avatar_border = avatar_w if avatar_w < avatar_h else avatar_h | 58 | avatar_border = avatar_w if avatar_w < avatar_h else avatar_h |
58 | avatar_crop_region = (0, 0, avatar_border, avatar_border) | 59 | avatar_crop_region = (0, 0, avatar_border, avatar_border) |
59 | avatar = avatar.crop(avatar_crop_region) | 60 | avatar = avatar.crop(avatar_crop_region) |
60 | 61 | ||
61 | avatar_96x96 = avatar.resize((96, 96), Image.ANTIALIAS) | 62 | avatar_96x96 = avatar.resize((96, 96), Image.ANTIALIAS) |
62 | avatar_48x48 = avatar.resize((48, 48), Image.ANTIALIAS) | 63 | avatar_48x48 = avatar.resize((48, 48), Image.ANTIALIAS) |
63 | avatar_32x32 = avatar.resize((32, 32), Image.ANTIALIAS) | 64 | avatar_32x32 = avatar.resize((32, 32), Image.ANTIALIAS) |
64 | path = os.path.dirname(__file__) | 65 | path = os.path.dirname(__file__) |
65 | avatar_96x96.save(os.path.join(path, '../static/avatar/b_%s.png' % avatar_name), 'PNG') | 66 | avatar_96x96.save(os.path.join(path, '../static/avatar/b_%s.png' % avatar_name), 'PNG') |
66 | avatar_48x48.save(os.path.join(path, '../static/avatar/m_%s.png' % avatar_name), 'PNG') | 67 | avatar_48x48.save(os.path.join(path, '../static/avatar/m_%s.png' % avatar_name), 'PNG') |
67 | avatar_32x32.save(os.path.join(path, '../static/avatar/s_%s.png' % avatar_name), 'PNG') | 68 | avatar_32x32.save(os.path.join(path, '../static/avatar/s_%s.png' % avatar_name), 'PNG') |
68 | user.avatar = '%s.png' % avatar_name | 69 | user.avatar = '%s.png' % avatar_name |
69 | user.updated = timezone.now() | 70 | user.updated = timezone.now() |
70 | user.save() | 71 | user.save() |
71 | return get_setting_avatar(request) | 72 | return get_setting_avatar(request) |
72 | 73 | ||
73 | 74 | ||
74 | @login_required | 75 | @login_required |
75 | def get_settingpwd(request, **kwargs): | 76 | def get_settingpwd(request, **kwargs): |
76 | return render_to_response('user/setting_password.html', kwargs, | 77 | return render_to_response('user/setting_password.html', kwargs, |
77 | context_instance=RequestContext(request)) | 78 | context_instance=RequestContext(request)) |
78 | 79 | ||
79 | 80 | ||
80 | @login_required | 81 | @login_required |
81 | def post_settingpwd(request): | 82 | def post_settingpwd(request): |
82 | form = SettingPasswordForm(request) | 83 | form = SettingPasswordForm(request) |
83 | if not form.is_valid(): | 84 | if not form.is_valid(): |
84 | return get_settingpwd(request, errors=form.errors) | 85 | return get_settingpwd(request, errors=form.errors) |
85 | 86 | ||
86 | user = request.user | 87 | user = request.user |
87 | password = form.cleaned_data.get('password') | 88 | password = form.cleaned_data.get('password') |
88 | user.set_password(password) | 89 | user.set_password(password) |
89 | user.updated = timezone.now() | 90 | user.updated = timezone.now() |
90 | user.save() | 91 | user.save() |
91 | return get_settingpwd(request, success_message=u'您的用户密码已更新') | 92 | return get_settingpwd(request, success_message=u'您的用户密码已更新') |
92 | 93 | ||
93 | 94 | ||
94 | def get_forgotpwd(request, **kwargs): | 95 | def get_forgotpwd(request, **kwargs): |
95 | auth.logout(request) | 96 | auth.logout(request) |
96 | return render_to_response('user/forgot_password.html', kwargs, | 97 | return render_to_response('user/forgot_password.html', kwargs, |
97 | context_instance=RequestContext(request)) | 98 | context_instance=RequestContext(request)) |
98 | 99 | ||
99 | 100 | ||
100 | def post_forgotpwd(request): | 101 | def post_forgotpwd(request): |
101 | form = ForgotPasswordForm(request.POST) | 102 | form = ForgotPasswordForm(request.POST) |
102 | if not form.is_valid(): | 103 | if not form.is_valid(): |
103 | return get_login(request, errors=form.errors) | 104 | return get_login(request, errors=form.errors) |
104 | 105 | ||
105 | user = form.get_user() | 106 | user = form.get_user() |
106 | 107 | ||
107 | new_password = uuid.uuid1().hex | 108 | new_password = uuid.uuid1().hex |
108 | user.set_password(new_password) | 109 | user.set_password(new_password) |
109 | user.updated = timezone.now() | 110 | user.updated = timezone.now() |
110 | user.save() | 111 | user.save() |
111 | 112 | ||
112 | # 给用户发送新密码 | 113 | # 给用户发送新密码 |
113 | mail_title = u'前端社区(F2E.im)找回密码' | 114 | mail_title = u'前端社区(F2E.im)找回密码' |
114 | var = {'email': user.email, 'new_password': new_password} | 115 | var = {'email': user.email, 'new_password': new_password} |
115 | mail_content = loader.get_template('user/forgot_password_mail.html').render(Context(var)) | 116 | mail_content = loader.get_template('user/forgot_password_mail.html').render(Context(var)) |
116 | sendmail(mail_title, mail_content, user.email) | 117 | sendmail(mail_title, mail_content, user.email) |
117 | 118 | ||
118 | return get_forgotpwd(request, success_message=u'新密码已发送至您的注册邮箱') | 119 | return get_forgotpwd(request, success_message=u'新密码已发送至您的注册邮箱') |
119 | 120 | ||
120 | 121 | ||
121 | def get_login(request, **kwargs): | 122 | def get_login(request, **kwargs): |
122 | auth.logout(request) | 123 | auth.logout(request) |
123 | return render_to_response('user/login.html', kwargs, | 124 | return render_to_response('user/login.html', kwargs, |
124 | context_instance=RequestContext(request)) | 125 | context_instance=RequestContext(request)) |
125 | 126 | ||
126 | def post_login(request): | 127 | def post_login(request): |
127 | form = LoginForm(request.POST) | 128 | form = LoginForm(request.POST) |
128 | if not form.is_valid(): | 129 | if not form.is_valid(): |
129 | return get_login(request, errors=form.errors) | 130 | return get_login(request, errors=form.errors) |
130 | 131 | ||
131 | user = form.get_user() | 132 | user_info = form.get_user() |
132 | auth.login(request, user) | 133 | pt = user_info.get('pt') |
133 | 134 | pu = user_info.get('pu') | |
134 | if user.is_staff: | 135 | t = redirect(request.REQUEST.get('next', '/')) |
135 | return redirect(request.REQUEST.get('next', '/manage/admin/')) | 136 | t.set_cookie('pt', pt, 864000) |
137 | t.set_cookie('pu', pu, 864000) | ||
136 | 138 | ||
137 | return redirect(request.REQUEST.get('next', '/')) | 139 | return t |
138 | 140 | ||
139 | 141 | ||
140 | def get_logout(request): | 142 | def get_logout(request): |
141 | auth.logout(request) | 143 | auth.logout(request) |
142 | return redirect(request.REQUEST.get('next', '/')) | 144 | return redirect(request.REQUEST.get('next', '/')) |
143 | 145 | ||
144 | 146 | ||
145 | def get_register(request, **kwargs): | 147 | def get_register(request, **kwargs): |
146 | auth.logout(request) | 148 | auth.logout(request) |
147 | return render_to_response('user/register.html', kwargs, | 149 | return render_to_response('user/register.html', kwargs, |
148 | context_instance=RequestContext(request)) | 150 | context_instance=RequestContext(request)) |
149 | 151 | ||
150 | 152 | ||
151 | def post_register(request): | 153 | def post_register(request): |
152 | form = RegisterForm(request.POST) | 154 | form = RegisterForm(request.POST) |
153 | 155 | ||
154 | if not form.is_valid(): | 156 | if not form.is_valid(): |
155 | return get_register(request, errors=form.errors) | 157 | return get_register(request, errors=form.errors) |
156 | 158 | ||
157 | user = form.save() | 159 | user = form.save() |
158 | if user: | 160 | if user: |
159 | # 注册成功,发送邮件到用户邮箱 | 161 | # 注册成功,发送邮件到用户邮箱 |
160 | # mail_title = u'微信小程序开发社区注册成功通知' | 162 | # mail_title = u'微信小程序开发社区注册成功通知' |
161 | # mail_content = loader.get_template('user/register_mail.html').render(Context({})) | 163 | # mail_content = loader.get_template('user/register_mail.html').render(Context({})) |
162 | # sendmail(mail_title, mail_content, user.email) | 164 | # sendmail(mail_title, mail_content, user.email) |
163 | pass | 165 | pass |
164 | 166 | ||
165 | return redirect(settings.LOGIN_URL) | 167 | return redirect(settings.LOGIN_URL) |
166 | 168 |
middlewares/__init__.py
middlewares/session_middleware.py
File was created | 1 | # coding: utf-8 | |
2 | |||
3 | import requests | ||
4 | from django.conf import settings | ||
5 | from django.core.cache import caches | ||
6 | from django.contrib.auth import get_user_model | ||
7 | from django.contrib.auth.models import AnonymousUser | ||
8 | |||
9 | |||
10 | class SessionWithoutLocalUserMiddleware(object): | ||
11 | """ | ||
12 | 统一权限(认证)中间件,Django系统本地不保存用户的情况使用 | ||
13 | """ | ||
14 | |||
15 | def __init__(self): | ||
16 | self.cache_alias = settings.CACHE_MIDDLEWARE_ALIAS | ||
17 | self.cache = caches[self.cache_alias] | ||
18 | self.UserModel = get_user_model() | ||
19 | |||
20 | def process_request(self, request): | ||
21 | if hasattr(request, "user") and getattr(request.user, "is_superuser", False): | ||
22 | # 对于Django系统的admin用户,这里不做任何处理 | ||
23 | pass | ||
24 | else: | ||
25 | pt = request.COOKIES.get('pt') | ||
26 | pu = request.COOKIES.get('pu') | ||
27 | username = request.COOKIES.get('username') | ||
28 | if pt and pu: | ||
29 | # 查询session状态成功的情况,构造QCCRUser | ||
30 | user = XYTUser(username, pu, pt) | ||
31 | request.user = user | ||
32 | else: | ||
33 | # 拿不到统一认证的session,将当前用户设为匿名用户 | ||
34 | request.user = AnonymousUser() | ||
35 | |||
36 | |||
37 | class Manager(object): | ||
38 | |||
39 | def __init__(self): | ||
40 | self.auth_domain = 'https://api.xiuyetang.com/sys/user/login' | ||
41 | |||
42 | |||
43 | class XYTUser(object): | ||
44 | id = None | ||
45 | pk = None | ||
46 | username = '' | ||
47 | sessionId = '' | ||
48 | accountNo = '' | ||
49 | employeeName = '' | ||
50 | employeeId = 0 | ||
51 | employeeNo = '' | ||
52 | employeeTel = '' | ||
53 | deptIds = '' | ||
54 | email = '' | ||
55 | entryTime = '' | ||
56 | uid = '' | ||
57 | is_staff = False | ||
58 | is_active = False | ||
59 | is_superuser = False | ||
60 | _groups = '' | ||
61 | _user_permissions = '' | ||
62 | |||
63 | def __init__(self, username, pu, pt): | ||
64 | self.username = username | ||
65 | self.id = pu | ||
66 | self.pk = pu | ||
67 | self.sessionId = pt | ||
68 | |||
69 | def __str__(self): | ||
70 | return self.username | ||
71 | |||
72 | def __eq__(self, other): | ||
73 | return self.username == other.username | ||
74 | |||
75 | def __ne__(self, other): | ||
76 | return not self.__eq__(other) | ||
77 | |||
78 | def __hash__(self): | ||
79 | return hash(self.username) | ||
80 | |||
81 | def save(self): | ||
82 | raise NotImplementedError("Django doesn't provide a DB representation for QCCRUser. User info in LDAP.") | ||
83 | |||
84 | def delete(self): | ||
85 | raise NotImplementedError("Django doesn't provide a DB representation for QCCRUser. User info in LDAP.") | ||
86 | |||
87 | def set_password(self, raw_password): | ||
88 | raise NotImplementedError("Django doesn't provide a DB representation for QCCRUser. Password in LDAP.") | ||
89 | |||
90 | def check_password(self, raw_password): | ||
91 | raise NotImplementedError("Django doesn't provide a DB representation for QCCRUser. Password in LDAP.") | ||
92 | |||
93 | def _get_groups(self): | ||
94 | return self._groups | ||
95 | |||
96 | groups = property(_get_groups) | ||
97 | |||
98 | def _get_user_permissions(self): | ||
99 | return self._user_permissions | ||
100 | |||
101 | user_permissions = property(_get_user_permissions) | ||
102 | |||
103 | def get_group_permissions(self, obj=None): | ||
104 | return set() | ||
105 | |||
106 | @property | ||
107 | def is_anonymous(self): | ||
108 | return lambda: False | ||
109 | |||
110 | @property | ||
111 | def is_authenticated(self): | ||
112 | return lambda: True | ||
113 | |||
114 | def get_username(self): | ||
115 | return self.username |
xp/settings.py
1 | # coding: utf-8 | 1 | # coding: utf-8 |
2 | # Django settings for xp project. | 2 | # Django settings for xp project. |
3 | 3 | ||
4 | DEBUG = True | 4 | DEBUG = True |
5 | TEMPLATE_DEBUG = DEBUG | 5 | TEMPLATE_DEBUG = DEBUG |
6 | 6 | ||
7 | ADMINS = ( | 7 | ADMINS = ( |
8 | # ('Your Name', 'your_email@example.com'), | 8 | # ('Your Name', 'your_email@example.com'), |
9 | ) | 9 | ) |
10 | 10 | ||
11 | MANAGERS = ADMINS | 11 | MANAGERS = ADMINS |
12 | 12 | ||
13 | DATABASES = { | 13 | DATABASES = { |
14 | 'default': { | 14 | 'default': { |
15 | 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. | 15 | 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. |
16 | 'NAME': 'forum', # Or path to database file if using sqlite3. | 16 | 'NAME': 'forum', # Or path to database file if using sqlite3. |
17 | # The following settings are not used with sqlite3: | 17 | # The following settings are not used with sqlite3: |
18 | 'USER': 'root', | 18 | 'USER': 'root', |
19 | 'PASSWORD': 'nineteen', | 19 | 'PASSWORD': 'zzc', |
20 | 'HOST': '127.0.0.1', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. | 20 | 'HOST': '127.0.0.1', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. |
21 | 'PORT': '3306', # Set to empty string for default. | 21 | 'PORT': '3306', # Set to empty string for default. |
22 | } | 22 | } |
23 | } | 23 | } |
24 | 24 | ||
25 | # Hosts/domain names that are valid for this site; required if DEBUG is False | 25 | # Hosts/domain names that are valid for this site; required if DEBUG is False |
26 | # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts | 26 | # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts |
27 | ALLOWED_HOSTS = ['*'] | 27 | ALLOWED_HOSTS = ['*'] |
28 | 28 | ||
29 | # Local time zone for this installation. Choices can be found here: | 29 | # Local time zone for this installation. Choices can be found here: |
30 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name | 30 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name |
31 | # although not all choices may be available on all operating systems. | 31 | # although not all choices may be available on all operating systems. |
32 | # In a Windows environment this must be set to your system time zone. | 32 | # In a Windows environment this must be set to your system time zone. |
33 | TIME_ZONE = 'Asia/Shanghai' | 33 | TIME_ZONE = 'Asia/Shanghai' |
34 | 34 | ||
35 | # Language code for this installation. All choices can be found here: | 35 | # Language code for this installation. All choices can be found here: |
36 | # http://www.i18nguy.com/unicode/language-identifiers.html | 36 | # http://www.i18nguy.com/unicode/language-identifiers.html |
37 | LANGUAGE_CODE = 'zh-CN' | 37 | LANGUAGE_CODE = 'zh-CN' |
38 | 38 | ||
39 | SITE_ID = 1 | 39 | SITE_ID = 1 |
40 | 40 | ||
41 | # If you set this to False, Django will make some optimizations so as not | 41 | # If you set this to False, Django will make some optimizations so as not |
42 | # to load the internationalization machinery. | 42 | # to load the internationalization machinery. |
43 | USE_I18N = True # 只有用admin的时候需要开启 | 43 | USE_I18N = True # 只有用admin的时候需要开启 |
44 | 44 | ||
45 | # If you set this to False, Django will not format dates, numbers and | 45 | # If you set this to False, Django will not format dates, numbers and |
46 | # calendars according to the current locale. | 46 | # calendars according to the current locale. |
47 | USE_L10N = False | 47 | USE_L10N = False |
48 | 48 | ||
49 | # If you set this to False, Django will not use timezone-aware datetimes. | 49 | # If you set this to False, Django will not use timezone-aware datetimes. |
50 | USE_TZ = False | 50 | USE_TZ = False |
51 | 51 | ||
52 | # Absolute filesystem path to the directory that will hold user-uploaded files. | 52 | # Absolute filesystem path to the directory that will hold user-uploaded files. |
53 | # Example: "/var/www/example.com/media/" | 53 | # Example: "/var/www/example.com/media/" |
54 | MEDIA_ROOT = '' | 54 | MEDIA_ROOT = '' |
55 | 55 | ||
56 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a | 56 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a |
57 | # trailing slash. | 57 | # trailing slash. |
58 | # Examples: "http://example.com/media/", "http://media.example.com/" | 58 | # Examples: "http://example.com/media/", "http://media.example.com/" |
59 | MEDIA_URL = '' | 59 | MEDIA_URL = '' |
60 | 60 | ||
61 | # Absolute path to the directory static files should be collected to. | 61 | # Absolute path to the directory static files should be collected to. |
62 | # Don't put anything in this directory yourself; store your static files | 62 | # Don't put anything in this directory yourself; store your static files |
63 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. | 63 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. |
64 | # Example: "/var/www/example.com/static/" | 64 | # Example: "/var/www/example.com/static/" |
65 | STATIC_ROOT = '' | 65 | STATIC_ROOT = '' |
66 | 66 | ||
67 | # URL prefix for static files. | 67 | # URL prefix for static files. |
68 | # Example: "http://example.com/static/", "http://static.example.com/" | 68 | # Example: "http://example.com/static/", "http://static.example.com/" |
69 | STATIC_URL = '/static/' | 69 | STATIC_URL = '/static/' |
70 | 70 | ||
71 | # Additional locations of static files | 71 | # Additional locations of static files |
72 | STATICFILES_DIRS = ( | 72 | STATICFILES_DIRS = ( |
73 | # Put strings here, like "/home/html/static" or "C:/www/django/static". | 73 | # Put strings here, like "/home/html/static" or "C:/www/django/static". |
74 | # Always use forward slashes, even on Windows. | 74 | # Always use forward slashes, even on Windows. |
75 | # Don't forget to use absolute paths, not relative paths. | 75 | # Don't forget to use absolute paths, not relative paths. |
76 | ) | 76 | ) |
77 | 77 | ||
78 | # List of finder classes that know how to find static files in | 78 | # List of finder classes that know how to find static files in |
79 | # various locations. | 79 | # various locations. |
80 | STATICFILES_FINDERS = ( | 80 | STATICFILES_FINDERS = ( |
81 | 'django.contrib.staticfiles.finders.FileSystemFinder', | 81 | 'django.contrib.staticfiles.finders.FileSystemFinder', |
82 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', | 82 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', |
83 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder', | 83 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder', |
84 | ) | 84 | ) |
85 | 85 | ||
86 | # Make this unique, and don't share it with anybody. | 86 | # Make this unique, and don't share it with anybody. |
87 | SECRET_KEY = 'h6=yzee&jze#4p1@twhksg1wg6hv%pzwomw(!o($qsly%lzlhe' | 87 | SECRET_KEY = 'h6=yzee&jze#4p1@twhksg1wg6hv%pzwomw(!o($qsly%lzlhe' |
88 | 88 | ||
89 | # List of callables that know how to import templates from various sources. | 89 | # List of callables that know how to import templates from various sources. |
90 | TEMPLATE_LOADERS = ( | 90 | TEMPLATE_LOADERS = ( |
91 | 'django.template.loaders.filesystem.Loader', | 91 | 'django.template.loaders.filesystem.Loader', |
92 | 'django.template.loaders.app_directories.Loader', | 92 | 'django.template.loaders.app_directories.Loader', |
93 | # 'django.template.loaders.eggs.Loader', | 93 | # 'django.template.loaders.eggs.Loader', |
94 | ) | 94 | ) |
95 | 95 | ||
96 | MIDDLEWARE_CLASSES = ( | 96 | MIDDLEWARE_CLASSES = ( |
97 | 'django.middleware.common.CommonMiddleware', | 97 | 'django.middleware.common.CommonMiddleware', |
98 | 'django.contrib.sessions.middleware.SessionMiddleware', | 98 | 'django.contrib.sessions.middleware.SessionMiddleware', |
99 | 'django.middleware.csrf.CsrfViewMiddleware', # 开启了CSRF,记得在POST表单中加{% csrf_token %},使用RequestContext | 99 | 'django.middleware.csrf.CsrfViewMiddleware', # 开启了CSRF,记得在POST表单中加{% csrf_token %},使用RequestContext |
100 | 'django.contrib.auth.middleware.AuthenticationMiddleware', | 100 | 'django.contrib.auth.middleware.AuthenticationMiddleware', |
101 | 'django.contrib.messages.middleware.MessageMiddleware', | 101 | 'django.contrib.messages.middleware.MessageMiddleware', |
102 | # Uncomment the next line for simple clickjacking protection: | 102 | # Uncomment the next line for simple clickjacking protection: |
103 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware', | 103 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware', |
104 | 'django.middleware.cache.FetchFromCacheMiddleware', # 缓存中间件,必须放在最后 | 104 | 'django.middleware.cache.FetchFromCacheMiddleware', # 缓存中间件,必须放在最后 |
105 | ) | 105 | ) |
106 | 106 | ||
107 | ROOT_URLCONF = 'xp.urls' | 107 | ROOT_URLCONF = 'xp.urls' |
108 | 108 | ||
109 | # Python dotted path to the WSGI application used by Django's runserver. | 109 | # Python dotted path to the WSGI application used by Django's runserver. |
110 | WSGI_APPLICATION = 'xp.wsgi.application' | 110 | WSGI_APPLICATION = 'xp.wsgi.application' |
111 | 111 | ||
112 | TEMPLATE_DIRS = ( | 112 | TEMPLATE_DIRS = ( |
113 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". | 113 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". |
114 | # Always use forward slashes, even on Windows. | 114 | # Always use forward slashes, even on Windows. |
115 | # Don't forget to use absolute paths, not relative paths. | 115 | # Don't forget to use absolute paths, not relative paths. |
116 | ) | 116 | ) |
117 | 117 | ||
118 | TEMPLATE_CONTEXT_PROCESSORS = ( # F2E中有current_user对象和request对象,这里设置可在模板中使用RquestContext | 118 | TEMPLATE_CONTEXT_PROCESSORS = ( # F2E中有current_user对象和request对象,这里设置可在模板中使用RquestContext |
119 | 'django.contrib.auth.context_processors.auth', # user对象等等 | 119 | 'django.contrib.auth.context_processors.auth', # user对象等等 |
120 | 'django.core.context_processors.request', # request对象等等 | 120 | 'django.core.context_processors.request', # request对象等等 |
121 | 'django.core.context_processors.static', # 在模板中使用{{ STATIC_URL }}获取静态文件路径 | 121 | 'django.core.context_processors.static', # 在模板中使用{{ STATIC_URL }}获取静态文件路径 |
122 | 'forum.context_processors.custom_proc', # 自定义模板上下文处理器 | 122 | 'forum.context_processors.custom_proc', # 自定义模板上下文处理器 |
123 | ) | 123 | ) |
124 | 124 | ||
125 | INSTALLED_APPS = ( | 125 | INSTALLED_APPS = ( |
126 | 'django.contrib.auth', | 126 | 'django.contrib.auth', |
127 | 'django.contrib.contenttypes', | 127 | 'django.contrib.contenttypes', |
128 | 'django.contrib.sessions', | 128 | 'django.contrib.sessions', |
129 | 'django.contrib.sites', | 129 | 'django.contrib.sites', |
130 | 'django.contrib.messages', | 130 | 'django.contrib.messages', |
131 | 'django.contrib.staticfiles', | 131 | 'django.contrib.staticfiles', |
132 | # Uncomment the next line to enable the admin: | 132 | # Uncomment the next line to enable the admin: |
133 | 'django.contrib.admin', | 133 | 'django.contrib.admin', |
134 | # Uncomment the next line to enable admin documentation: | 134 | # Uncomment the next line to enable admin documentation: |
135 | # 'django.contrib.admindocs', | 135 | # 'django.contrib.admindocs', |
136 | 'django.contrib.sitemaps', # Django sitemap framework | 136 | 'django.contrib.sitemaps', # Django sitemap framework |
137 | 'gunicorn', | 137 | 'gunicorn', |
138 | 'forum', | 138 | 'forum', |
139 | ) | 139 | ) |
140 | 140 | ||
141 | # A sample logging configuration. The only tangible logging | 141 | # A sample logging configuration. The only tangible logging |
142 | # performed by this configuration is to send an email to | 142 | # performed by this configuration is to send an email to |
143 | # the site admins on every HTTP 500 error when DEBUG=False. | 143 | # the site admins on every HTTP 500 error when DEBUG=False. |
144 | # See http://docs.djangoproject.com/en/dev/topics/logging for | 144 | # See http://docs.djangoproject.com/en/dev/topics/logging for |
145 | # more details on how to customize your logging configuration. | 145 | # more details on how to customize your logging configuration. |
146 | LOGGING = { | 146 | LOGGING = { |
147 | 'version': 1, | 147 | 'version': 1, |
148 | 'disable_existing_loggers': False, | 148 | 'disable_existing_loggers': False, |
149 | 'filters': { | 149 | 'filters': { |
150 | 'require_debug_false': { | 150 | 'require_debug_false': { |
151 | '()': 'django.utils.log.RequireDebugFalse' | 151 | '()': 'django.utils.log.RequireDebugFalse' |
152 | } | 152 | } |
153 | }, | 153 | }, |
154 | 'handlers': { | 154 | 'handlers': { |
155 | 'mail_admins': { | 155 | 'mail_admins': { |
156 | 'level': 'ERROR', | 156 | 'level': 'ERROR', |
157 | 'filters': ['require_debug_false'], | 157 | 'filters': ['require_debug_false'], |
158 | 'class': 'django.utils.log.AdminEmailHandler' | 158 | 'class': 'django.utils.log.AdminEmailHandler' |
159 | }, | 159 | }, |
160 | 'console': { | 160 | 'console': { |
161 | 'level': 'DEBUG', | 161 | 'level': 'DEBUG', |
162 | 'class': 'logging.StreamHandler', | 162 | 'class': 'logging.StreamHandler', |
163 | }, | 163 | }, |
164 | }, | 164 | }, |
165 | 'loggers': { | 165 | 'loggers': { |
166 | 'django.request': { | 166 | 'django.request': { |
167 | 'handlers': ['mail_admins'], | 167 | 'handlers': ['mail_admins'], |
168 | 'level': 'ERROR', | 168 | 'level': 'ERROR', |
169 | 'propagate': True, | 169 | 'propagate': True, |
170 | }, | 170 | }, |
171 | 'django.db.backends': { | 171 | 'django.db.backends': { |
172 | 'level': 'DEBUG', | 172 | 'level': 'DEBUG', |
173 | 'handlers': ['console'], | 173 | 'handlers': ['console'], |
174 | }, | 174 | }, |
175 | } | 175 | } |
176 | } | 176 | } |
177 | # | 177 | # |
178 | # CACHES = { # memcached缓存设置 | 178 | # CACHES = { # memcached缓存设置 |
179 | # 'default': { | 179 | # 'default': { |
180 | # 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', | 180 | # 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', |
181 | # 'LOCATION': '127.0.0.1:11211', | 181 | # 'LOCATION': '127.0.0.1:11211', |
182 | # } | 182 | # } |
183 | # } | 183 | # } |
184 | 184 | ||
185 | # SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 使用memcached存储session | 185 | # SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 使用memcached存储session |
186 | AUTH_DOMAIN = 'https://api.xiuyetang.com/service/user/login' | ||
186 | 187 | ||
187 | # 自定义User类 | 188 | # 自定义User类 |
188 | AUTH_USER_MODEL = 'forum.ForumUser' | 189 | AUTH_USER_MODEL = 'forum.ForumUser' |
189 | 190 | ||
190 | # 用户认证BackEnds | 191 | # 用户认证BackEnds |
191 | # AUTHENTICATION_BACKENDS = ('forum.backends.EmailAuthBackend',) | 192 | AUTHENTICATION_BACKENDS = ('forum.backends.EmailAuthBackend',) |
192 | 193 | ||
193 | # 默认登陆uri | 194 | # 默认登陆uri |
194 | LOGIN_URL = '/login/' | 195 | LOGIN_URL = '/login/' |
195 | 196 | ||
196 | # 发送邮件设置 | 197 | # 发送邮件设置 |
197 | EMAIL_HOST = 'smtp.qq.com' | 198 | EMAIL_HOST = 'smtp.qq.com' |
198 | EMAIL_PORT = 25 | 199 | EMAIL_PORT = 25 |
199 | EMAIL_HOST_USER= '*********' | 200 | EMAIL_HOST_USER= '*********' |
200 | EMAIL_HOST_PASSWORD= '******' | 201 | EMAIL_HOST_PASSWORD= '******' |
201 | DEFAULT_FROM_EMAIL = '*********@qq.com' | 202 | DEFAULT_FROM_EMAIL = '*********@qq.com' |
202 | 203 | ||
203 | # 注册用户保留关键字,非Django设置 | 204 | # 注册用户保留关键字,非Django设置 |
204 | RESERVED = ["user", "topic", "home", "setting", "forgot", "login", "logout", "register", "admin"] | 205 | RESERVED = ["user", "topic", "home", "setting", "forgot", "login", "logout", "register", "admin"] |
205 | 206 |