s="lines-code">
def upload_path(instance, old_filename):
|
|
|
@@ -38,14 +38,13 @@ class LatestAppInfo(CreateUpdateMixin):
|
|
38
|
38
|
def final_latest_url(self):
|
|
39
|
39
|
return self.latest_url or u'{}{}'.format(settings.DOMAIN, self.latest_app and self.latest_app.url)
|
|
40
|
40
|
|
|
41
|
|
- def _data(self):
|
|
|
41
|
+ @property
|
|
|
42
|
+ def data(self):
|
|
42
|
43
|
return {
|
|
43
|
44
|
'latest_version': self.latest_version,
|
|
44
|
45
|
'latest_url': self.final_latest_url,
|
|
45
|
46
|
}
|
|
46
|
47
|
|
|
47
|
|
- data = property(_data)
|
|
48
|
|
-
|
|
49
|
48
|
|
|
50
|
49
|
class SplashInfo(CreateUpdateMixin):
|
|
51
|
50
|
splash_image = models.ImageField(_(u'splash_image'), upload_to=upload_path, blank=True, null=True, help_text=u'启动页面图片')
|
|
|
|
@@ -63,15 +62,14 @@ class SplashInfo(CreateUpdateMixin):
|
|
63
|
62
|
def splash_image_url(self):
|
|
64
|
63
|
return self.splash_image and (settings.DOMAIN + self.splash_image.url)
|
|
65
|
64
|
|
|
66
|
|
- def _data(self):
|
|
|
65
|
+ @property
|
|
|
66
|
+ def data(self):
|
|
67
|
67
|
return {
|
|
68
|
68
|
'splash_image_url': self.splash_image_url,
|
|
69
|
69
|
'spalash_image_airtime': self.spalash_image_airtime,
|
|
70
|
70
|
'spalash_image_deadline': self.spalash_image_deadline,
|
|
71
|
71
|
}
|
|
72
|
72
|
|
|
73
|
|
- data = property(_data)
|
|
74
|
|
-
|
|
75
|
73
|
|
|
76
|
74
|
class FeedbackInfo(CreateUpdateMixin):
|
|
77
|
75
|
user_id = models.CharField(_(u'user_id'), max_length=255, blank=True, null=True, help_text=u'用户唯一标识')
|
|
|
|
@@ -83,3 +81,23 @@ class FeedbackInfo(CreateUpdateMixin):
|
|
83
|
81
|
|
|
84
|
82
|
def __unicode__(self):
|
|
85
|
83
|
return u'{0.pk}'.format(self)
|
|
|
84
|
+
|
|
|
85
|
+
|
|
|
86
|
+class GuestEntranceControlInfo(CreateUpdateMixin, PlatformMixin, VersionMixin):
|
|
|
87
|
+
|
|
|
88
|
+ class Meta:
|
|
|
89
|
+ verbose_name = _('guestentrancecontrolinfo')
|
|
|
90
|
+ verbose_name_plural = _('guestentrancecontrolinfo')
|
|
|
91
|
+
|
|
|
92
|
+ def __unicode__(self):
|
|
|
93
|
+ return u'{0.pk}'.format(self)
|
|
|
94
|
+
|
|
|
95
|
+ @property
|
|
|
96
|
+ def data(self):
|
|
|
97
|
+ return {
|
|
|
98
|
+ 'platform': self.platform,
|
|
|
99
|
+ 'min_adr': self.min_adr,
|
|
|
100
|
+ 'min_ios': self.min_ios,
|
|
|
101
|
+ 'max_adr': self.max_adr,
|
|
|
102
|
+ 'max_ios': self.max_ios,
|
|
|
103
|
+ }
|
|
|
|
@@ -3,6 +3,8 @@
|
|
3
|
3
|
from django.db import models
|
|
4
|
4
|
from django.utils.translation import ugettext_lazy as _
|
|
5
|
5
|
|
|
|
6
|
+from utils.version_utils import is_version_match
|
|
|
7
|
+
|
|
6
|
8
|
|
|
7
|
9
|
class CreateUpdateMixin(models.Model):
|
|
8
|
10
|
status = models.BooleanField(_(u'status'), default=True, help_text=_(u'状态'), db_index=True)
|
|
|
|
@@ -11,3 +13,38 @@ class CreateUpdateMixin(models.Model):
|
|
11
|
13
|
|
|
12
|
14
|
class Meta:
|
|
13
|
15
|
abstract = True
|
|
|
16
|
+
|
|
|
17
|
+
|
|
|
18
|
+class PlatformMixin(models.Model):
|
|
|
19
|
+ BOTH = 0
|
|
|
20
|
+ ADR = 1
|
|
|
21
|
+ IOS = 2
|
|
|
22
|
+
|
|
|
23
|
+ SUPPORT_PLATFORM = (
|
|
|
24
|
+ (BOTH, u'全平台'),
|
|
|
25
|
+ (ADR, u'Android'),
|
|
|
26
|
+ (IOS, u'iOS'),
|
|
|
27
|
+ )
|
|
|
28
|
+
|
|
|
29
|
+ platform = models.IntegerField(_(u'plat'), choices=SUPPORT_PLATFORM, default=BOTH, help_text=u'支持平台', db_index=True)
|
|
|
30
|
+
|
|
|
31
|
+ class Meta:
|
|
|
32
|
+ abstract = True
|
|
|
33
|
+
|
|
|
34
|
+
|
|
|
35
|
+class VersionMixin(models.Model):
|
|
|
36
|
+ min_adr = models.CharField(_(u'min_adr'), max_length=255, blank=True, null=True, help_text=u'Adr 最低版本')
|
|
|
37
|
+ min_ios = models.CharField(_(u'min_ios'), max_length=255, blank=True, null=True, help_text=u'iOS 最低版本')
|
|
|
38
|
+ max_adr = models.CharField(_(u'max_adr'), max_length=255, blank=True, null=True, help_text=u'Adr 最高版本')
|
|
|
39
|
+ max_ios = models.CharField(_(u'max_ios'), max_length=255, blank=True, null=True, help_text=u'iOS 最高版本')
|
|
|
40
|
+
|
|
|
41
|
+ def version_match(self, request):
|
|
|
42
|
+ return is_version_match(request, {
|
|
|
43
|
+ 'min_adr': self.min_adr,
|
|
|
44
|
+ 'min_ios': self.min_ios,
|
|
|
45
|
+ 'max_adr': self.max_adr,
|
|
|
46
|
+ 'max_ios': self.max_ios,
|
|
|
47
|
+ })
|
|
|
48
|
+
|
|
|
49
|
+ class Meta:
|
|
|
50
|
+ abstract = True
|
|
|
|
@@ -64,6 +64,7 @@ MIDDLEWARE_CLASSES = (
|
|
64
|
64
|
'django.contrib.messages.middleware.MessageMiddleware',
|
|
65
|
65
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
66
|
66
|
'django.middleware.security.SecurityMiddleware',
|
|
|
67
|
+ 'detect.middleware.UserAgentDetectionMiddleware',
|
|
67
|
68
|
)
|
|
68
|
69
|
|
|
69
|
70
|
MIDDLEWARE_CLASSES += ('multidomain.middleware.DomainMiddleware', )
|
|
|
|
@@ -254,6 +255,11 @@ GROUP_PER_PAGE = 20 # 群组每页数量
|
|
254
|
255
|
# 游客设置
|
|
255
|
256
|
GUEST_USER_ID = 'guest'
|
|
256
|
257
|
|
|
|
258
|
+# 版本设置
|
|
|
259
|
+MIN_VERSION = '0.0.0'
|
|
|
260
|
+MAX_VERSION = '999.999.999'
|
|
|
261
|
+CURRENT_VERSION = '1.0.0'
|
|
|
262
|
+
|
|
257
|
263
|
# 价格设置
|
|
258
|
264
|
LENSMAN_PHOTO_HAGGLE_MAX_TIMES = 3 # 摄影师照片最大砍价次数
|
|
259
|
265
|
|
|
|
|
@@ -1,10 +1,11 @@
|
|
1
|
1
|
CodeConvert==2.0.4
|
|
2
|
2
|
Django==1.8.4
|
|
3
|
3
|
MySQL-python==1.2.5
|
|
4
|
|
-TimeConvert==1.1.6
|
|
|
4
|
+TimeConvert==1.2.0
|
|
5
|
5
|
cryptography==1.2.1
|
|
6
|
6
|
django-curtail-uuid==1.0.0
|
|
7
|
|
-django-logit==1.0.0
|
|
|
7
|
+django-detect==1.0.3
|
|
|
8
|
+django-logit==1.0.2
|
|
8
|
9
|
django-multidomain==1.1.4
|
|
9
|
10
|
django-shortuuidfield==0.1.3
|
|
10
|
11
|
djangorestframework==3.3.1
|
|
|
|
@@ -17,4 +18,5 @@ pytz==2015.7
|
|
17
|
18
|
redis==2.10.5
|
|
18
|
19
|
shortuuid==0.4.2
|
|
19
|
20
|
uWSGI==2.0.11.1
|
|
20
|
|
-wechatpy==1.2.6
|
|
|
21
|
+versions==0.10.0
|
|
|
22
|
+wechatpy==1.2.8
|
|
|
|
@@ -26,7 +26,7 @@ class UserStatusCode(BaseStatusCode):
|
|
26
|
26
|
USER_PASSWORD_ERROR = StatusCodeField(400102, u'User Password Error', description=u'用户密码错误')
|
|
27
|
27
|
USERNAME_HAS_REGISTERED = StatusCodeField(400103, u'Username Has Registered', description=u'用户名已注册')
|
|
28
|
28
|
|
|
29
|
|
- GUEST_NOT_FOUND = StatusCodeField(400111, u'Guest Not Found', description=u'游客不存在')
|
|
|
29
|
+ GUEST_NOT_ALLOWED = StatusCodeField(400111, u'Guest Not ALLOWED', description=u'游客登录不允许')
|
|
30
|
30
|
|
|
31
|
31
|
|
|
32
|
32
|
class PhotoStatusCode(BaseStatusCode):
|
|
|
|
@@ -26,3 +26,6 @@ LENSMAN_PHOTO_ORDER_RECORD = 'lensman:photo:order:record:%s:%s' # STRING,摄
|
|
26
|
26
|
# 系统消息相关
|
|
27
|
27
|
SYSTEM_MESSAGE_READ_INFO = 'system:message:read:info:%s' # STRING,系统消息读取信息,user_id
|
|
28
|
28
|
SYSTEM_MESSAGE_DELETED_INFO = 'system:message:deleted:info:%s' # STRING,系统消息删除信息,user_id
|
|
|
29
|
+
|
|
|
30
|
+# 游客入口相关
|
|
|
31
|
+GUEST_ENTRANCE_CONTROL_INFO = 'guest:entrance:control:info' # STRING,游客入口控制信息
|
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
|
2
|
+
|
|
|
3
|
+import json
|
|
|
4
|
+
|
|
|
5
|
+from django.conf import settings
|
|
|
6
|
+
|
|
|
7
|
+from utils.redis.rkeys import GUEST_ENTRANCE_CONTROL_INFO
|
|
|
8
|
+
|
|
|
9
|
+
|
|
|
10
|
+r = settings.REDIS_CACHE
|
|
|
11
|
+
|
|
|
12
|
+
|
|
|
13
|
+# 游客入口控制相关
|
|
|
14
|
+
|
|
|
15
|
+
|
|
|
16
|
+def set_guest_entrance_control(gen):
|
|
|
17
|
+ """ 设置游客入口控制 """
|
|
|
18
|
+ r.set(GUEST_ENTRANCE_CONTROL_INFO, json.dumps(gen.data))
|
|
|
19
|
+ return gen.data
|
|
|
20
|
+
|
|
|
21
|
+
|
|
|
22
|
+def get_guest_entrance_control():
|
|
|
23
|
+ """ 获取游客入口控制 """
|
|
|
24
|
+ return json.loads(r.get(GUEST_ENTRANCE_CONTROL_INFO) or '{}')
|
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
|
2
|
+
|
|
|
3
|
+from django.conf import settings
|
|
|
4
|
+from versions import Version
|
|
|
5
|
+
|
|
|
6
|
+
|
|
|
7
|
+def is_version_match(request, vers={}):
|
|
|
8
|
+ minv, maxv = (vers.get('min_adr', ''), vers.get('max_adr', '')) if request.Android else (vers.get('min_ios', ''), vers.get('max_ios', ''))
|
|
|
9
|
+ return Version.parse(minv or settings.MIN_VERSION) <= Version.parse(
|
|
|
10
|
+ request.REQUEST.get('version', settings.CURRENT_VERSION)) <= Version.parse(maxv or settings.MAX_VERSION)
|