@@ -15,7 +15,7 @@ from curtail_uuid import CurtailUUID |
||
15 | 15 |
from TimeConvert import TimeConvert as tc |
16 | 16 |
|
17 | 17 |
|
18 |
-# curl -X POST -F username=xxxxxxx -F password=xxxxxxx http://api.xfoto.com.cn/login |
|
18 |
+# curl -X POST -F username=xxxxxxx -F password=xxxxxxx http://api.pai.ai/login |
|
19 | 19 |
def lesman_login_api(request): |
20 | 20 |
username = request.POST.get('username', '') |
21 | 21 |
password = request.POST.get('password', '') |
@@ -5,6 +5,7 @@ from django.conf.urls import url |
||
5 | 5 |
from account import views as account_views |
6 | 6 |
from group import views as group_views |
7 | 7 |
from photo import views as photo_views |
8 |
+from operation import views as op_views |
|
8 | 9 |
|
9 | 10 |
|
10 | 11 |
urlpatterns = [ |
@@ -44,3 +45,8 @@ urlpatterns += [ |
||
44 | 45 |
url(r'^s/(?P<session>\w+)$', photo_views.session_detail_api, name='session_detail_api'), # Session 详情 |
45 | 46 |
url(r'^p/(?P<photo>\w+)$', photo_views.photo_standard_api, name='photo_standard_api'), # standard thumbnail, available for free |
46 | 47 |
] |
48 |
+ |
|
49 |
+urlpatterns += [ |
|
50 |
+ url(r'^op/upgrade$', op_views.upgrade_api, name='upgrade_api'), # APP 升级 |
|
51 |
+ url(r'^op/splash$', op_views.splash_api, name='splash_api'), # 启动页面 |
|
52 |
+] |
@@ -0,0 +1,19 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+from __future__ import unicode_literals |
|
3 |
+ |
|
4 |
+from django.db import models, migrations |
|
5 |
+ |
|
6 |
+ |
|
7 |
+class Migration(migrations.Migration): |
|
8 |
+ |
|
9 |
+ dependencies = [ |
|
10 |
+ ('group', '0006_groupuserinfo_avatar'), |
|
11 |
+ ] |
|
12 |
+ |
|
13 |
+ operations = [ |
|
14 |
+ migrations.AlterField( |
|
15 |
+ model_name='groupuserinfo', |
|
16 |
+ name='user_status', |
|
17 |
+ field=models.IntegerField(default=0, verbose_name='user_status', choices=[(0, '\u7533\u8bf7\u4e2d'), (1, '\u5df2\u901a\u8fc7'), (2, '\u5df2\u62d2\u7edd'), (3, '\u5df2\u5220\u9664')]), |
|
18 |
+ ), |
|
19 |
+ ] |
@@ -77,6 +77,7 @@ class GroupUserInfo(CreateUpdateMixin): |
||
77 | 77 |
(APPLYING, u'申请中'), |
78 | 78 |
(PASSED, u'已通过'), |
79 | 79 |
(REFUSED, u'已拒绝'), |
80 |
+ (DELETED, u'已删除') |
|
80 | 81 |
) |
81 | 82 |
|
82 | 83 |
group_id = models.CharField(_(u'group_id'), max_length=255, blank=True, null=True, help_text=u'群组唯一标识', db_index=True) |
@@ -83,6 +83,8 @@ def group_detail_api(request): |
||
83 | 83 |
'message': u'群组不存在', |
84 | 84 |
}) |
85 | 85 |
|
86 |
+ # 判断用户是否已被丛群组移除 |
|
87 |
+ |
|
86 | 88 |
return JsonResponse({ |
87 | 89 |
'status': 200, |
88 | 90 |
'message': u'获取群组详情成功', |
@@ -0,0 +1,17 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from django.contrib import admin |
|
4 |
+ |
|
5 |
+from operation.models import LatestAppInfo, SplashInfo |
|
6 |
+ |
|
7 |
+ |
|
8 |
+class LatestAppInfoAdmin(admin.ModelAdmin): |
|
9 |
+ list_display = ('latest_version', 'latest_app', 'latest_url', 'status', 'created_at', 'updated_at') |
|
10 |
+ |
|
11 |
+ |
|
12 |
+class SplashInfoAdmin(admin.ModelAdmin): |
|
13 |
+ list_display = ('splash_image', 'spalash_image_airtime', 'spalash_image_deadline', 'status', 'created_at', 'updated_at') |
|
14 |
+ |
|
15 |
+ |
|
16 |
+admin.site.register(LatestAppInfo, LatestAppInfoAdmin) |
|
17 |
+admin.site.register(SplashInfo, SplashInfoAdmin) |
@@ -0,0 +1,46 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+from __future__ import unicode_literals |
|
3 |
+ |
|
4 |
+from django.db import models, migrations |
|
5 |
+import operation.models |
|
6 |
+ |
|
7 |
+ |
|
8 |
+class Migration(migrations.Migration): |
|
9 |
+ |
|
10 |
+ dependencies = [ |
|
11 |
+ ] |
|
12 |
+ |
|
13 |
+ operations = [ |
|
14 |
+ migrations.CreateModel( |
|
15 |
+ name='LatestAppInfo', |
|
16 |
+ fields=[ |
|
17 |
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), |
|
18 |
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')), |
|
19 |
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)), |
|
20 |
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)), |
|
21 |
+ ('latest_version', models.CharField(help_text='\u6700\u65b0\u7248\u672c', max_length=255, verbose_name='latest_version')), |
|
22 |
+ ('latest_app', models.FileField(help_text='\u6700\u65b0\u7248 APP', upload_to=operation.models.upload_path, null=True, verbose_name='latest_app', blank=True)), |
|
23 |
+ ('latest_url', models.URLField(help_text='\u6700\u65b0\u7248 APP \u94fe\u63a5', max_length=255, null=True, verbose_name='latest_url', blank=True)), |
|
24 |
+ ], |
|
25 |
+ options={ |
|
26 |
+ 'verbose_name': 'latestappinfo', |
|
27 |
+ 'verbose_name_plural': 'latestappinfo', |
|
28 |
+ }, |
|
29 |
+ ), |
|
30 |
+ migrations.CreateModel( |
|
31 |
+ name='SplashInfo', |
|
32 |
+ fields=[ |
|
33 |
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), |
|
34 |
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')), |
|
35 |
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)), |
|
36 |
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)), |
|
37 |
+ ('splash_image', models.ImageField(help_text='\u542f\u52a8\u9875\u9762\u56fe\u7247', upload_to=operation.models.upload_path, null=True, verbose_name='splash_image', blank=True)), |
|
38 |
+ ('spalash_image_airtime', models.DateTimeField(help_text='\u542f\u52a8\u9875\u9762\u56fe\u7247\u5f00\u59cb\u65e5\u671f', null=True, verbose_name='spalash_image_airtime', blank=True)), |
|
39 |
+ ('spalash_image_deadline', models.DateTimeField(help_text='\u542f\u52a8\u9875\u9762\u56fe\u7247\u622a\u6b62\u65e5\u671f', null=True, verbose_name='spalash_image_deadline', blank=True)), |
|
40 |
+ ], |
|
41 |
+ options={ |
|
42 |
+ 'verbose_name': 'splashinfo', |
|
43 |
+ 'verbose_name_plural': 'splashinfo', |
|
44 |
+ }, |
|
45 |
+ ), |
|
46 |
+ ] |
@@ -0,0 +1,73 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from django.conf import settings |
|
4 |
+from django.db import models |
|
5 |
+from django.utils.translation import ugettext_lazy as _ |
|
6 |
+ |
|
7 |
+from pai2.basemodels import CreateUpdateMixin |
|
8 |
+ |
|
9 |
+import datetime |
|
10 |
+import os |
|
11 |
+import time |
|
12 |
+ |
|
13 |
+ |
|
14 |
+def upload_path(instance, old_filename): |
|
15 |
+ extension = os.path.splitext(old_filename)[1].lower() |
|
16 |
+ today = datetime.datetime.today() |
|
17 |
+ return 'file/{year}{month}/{timestamp}{extension}'.format( |
|
18 |
+ year=today.year, |
|
19 |
+ month=today.month, |
|
20 |
+ timestamp=time.time(), |
|
21 |
+ extension=extension |
|
22 |
+ ) |
|
23 |
+ |
|
24 |
+ |
|
25 |
+class LatestAppInfo(CreateUpdateMixin): |
|
26 |
+ latest_version = models.CharField(_(u'latest_version'), max_length=255, help_text=u'最新版本') |
|
27 |
+ latest_app = models.FileField(_(u'latest_app'), upload_to=upload_path, blank=True, null=True, help_text=u'最新版 APP') |
|
28 |
+ latest_url = models.URLField(_(u'latest_url'), max_length=255, blank=True, null=True, help_text=u'最新版 APP 链接') |
|
29 |
+ |
|
30 |
+ class Meta: |
|
31 |
+ verbose_name = _('latestappinfo') |
|
32 |
+ verbose_name_plural = _('latestappinfo') |
|
33 |
+ |
|
34 |
+ def __unicode__(self): |
|
35 |
+ return u'{0.pk}'.format(self) |
|
36 |
+ |
|
37 |
+ @property |
|
38 |
+ def final_latest_url(self): |
|
39 |
+ return self.latest_url or u'{0}{1}'.format(settings.DOMAIN, self.latest_app and self.latest_app.url) |
|
40 |
+ |
|
41 |
+ def _data(self): |
|
42 |
+ return { |
|
43 |
+ 'latest_version': self.latest_version, |
|
44 |
+ 'latest_url': self.final_latest_url, |
|
45 |
+ } |
|
46 |
+ |
|
47 |
+ data = property(_data) |
|
48 |
+ |
|
49 |
+ |
|
50 |
+class SplashInfo(CreateUpdateMixin): |
|
51 |
+ splash_image = models.ImageField(_(u'splash_image'), upload_to=upload_path, blank=True, null=True, help_text=u'启动页面图片') |
|
52 |
+ spalash_image_airtime = models.DateTimeField(_(u'spalash_image_airtime'), blank=True, null=True, help_text=u'启动页面图片开始日期') |
|
53 |
+ spalash_image_deadline = models.DateTimeField(_(u'spalash_image_deadline'), blank=True, null=True, help_text=u'启动页面图片截止日期') |
|
54 |
+ |
|
55 |
+ class Meta: |
|
56 |
+ verbose_name = _('splashinfo') |
|
57 |
+ verbose_name_plural = _('splashinfo') |
|
58 |
+ |
|
59 |
+ def __unicode__(self): |
|
60 |
+ return u'{0.pk}'.format(self) |
|
61 |
+ |
|
62 |
+ @property |
|
63 |
+ def splash_image_url(self): |
|
64 |
+ return self.splash_image and (settings.DOMAIN + self.splash_image.url) |
|
65 |
+ |
|
66 |
+ def _data(self): |
|
67 |
+ return { |
|
68 |
+ 'splash_image_url': self.splash_image_url, |
|
69 |
+ 'spalash_image_airtime': self.spalash_image_airtime, |
|
70 |
+ 'spalash_image_deadline': self.spalash_image_deadline, |
|
71 |
+ } |
|
72 |
+ |
|
73 |
+ data = property(_data) |
@@ -0,0 +1,3 @@ |
||
1 |
+from django.test import TestCase |
|
2 |
+ |
|
3 |
+# Create your tests here. |
@@ -0,0 +1,37 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from django.conf import settings |
|
4 |
+from django.core.files.storage import default_storage |
|
5 |
+from django.db import transaction |
|
6 |
+from django.http import JsonResponse |
|
7 |
+from django.shortcuts import render, redirect |
|
8 |
+ |
|
9 |
+from operation.models import LatestAppInfo, SplashInfo |
|
10 |
+ |
|
11 |
+ |
|
12 |
+def upgrade_api(request): |
|
13 |
+ try: |
|
14 |
+ appinfo = LatestAppInfo.objects.all()[0].data |
|
15 |
+ except IndexError: |
|
16 |
+ appinfo = {} |
|
17 |
+ |
|
18 |
+ return JsonResponse({ |
|
19 |
+ 'status': 200, |
|
20 |
+ 'message': u'获取最新版信息成功', |
|
21 |
+ 'data': { |
|
22 |
+ 'appinfo': appinfo, |
|
23 |
+ }, |
|
24 |
+ }) |
|
25 |
+ |
|
26 |
+ |
|
27 |
+def splash_api(request): |
|
28 |
+ splashes = SplashInfo.objects.all() |
|
29 |
+ splashes = [splash.data for splash in splashes] |
|
30 |
+ |
|
31 |
+ return JsonResponse({ |
|
32 |
+ 'status': 200, |
|
33 |
+ 'message': u'获取最新版信息成功', |
|
34 |
+ 'data': { |
|
35 |
+ 'splashes': splashes, |
|
36 |
+ }, |
|
37 |
+ }) |
@@ -45,6 +45,7 @@ INSTALLED_APPS = ( |
||
45 | 45 |
'account', |
46 | 46 |
'group', |
47 | 47 |
'photo', |
48 |
+ 'operation', |
|
48 | 49 |
) |
49 | 50 |
|
50 | 51 |
INSTALLED_APPS += ('multidomain', ) |
@@ -11,7 +11,7 @@ server { |
||
11 | 11 |
# the port your site will be served on |
12 | 12 |
listen 80; |
13 | 13 |
# the domain name it will serve for |
14 |
- server_name .img.xfoto.com.cn; # substitute your machine's IP address or FQDN |
|
14 |
+ server_name .img.pai.ai .img.xfoto.com.cn; # substitute your machine's IP address or FQDN |
|
15 | 15 |
charset utf-8; |
16 | 16 |
|
17 | 17 |
# max upload size |
@@ -36,7 +36,7 @@ server { |
||
36 | 36 |
# the port your site will be served on |
37 | 37 |
listen 80; |
38 | 38 |
# the domain name it will serve for |
39 |
- server_name .api.xfoto.com.cn; # substitute your machine's IP address or FQDN |
|
39 |
+ server_name .api.pai.ai .api.xfoto.com.cn; # substitute your machine's IP address or FQDN |
|
40 | 40 |
charset utf-8; |
41 | 41 |
|
42 | 42 |
# max upload size |
@@ -64,7 +64,7 @@ server { |
||
64 | 64 |
# the port your site will be served on |
65 | 65 |
listen 80; |
66 | 66 |
# the domain name it will serve for |
67 |
- server_name .xfoto.com.cn; # substitute your machine's IP address or FQDN |
|
67 |
+ server_name .pai.ai .xfoto.com.cn; # substitute your machine's IP address or FQDN |
|
68 | 68 |
charset utf-8; |
69 | 69 |
|
70 | 70 |
# max upload size |
@@ -37,7 +37,7 @@ def uuid_init(request): |
||
37 | 37 |
}) |
38 | 38 |
|
39 | 39 |
|
40 |
-# curl -X POST -F user=xxxxxxx -F num=100 http://api.xfoto.com.cn/uuid |
|
40 |
+# curl -X POST -F user=xxxxxxx -F num=100 http://api.pai.ai/uuid |
|
41 | 41 |
@transaction.atomic |
42 | 42 |
def uuid(request): |
43 | 43 |
lensman_id = request.POST.get('user', '') |
@@ -67,7 +67,7 @@ def uuid(request): |
||
67 | 67 |
# name with the symbol <. The difference between @ and < is then that @ makes a file get attached in the post as a file upload, |
68 | 68 |
# while the < makes a text field and just get the contents for that text field from a file. |
69 | 69 |
# |
70 |
-# curl -X POST -F user=xxxxxxx -F session=xxxxxxx -F photo_id=xxxxxxx -F photo=@xxxxxxx.jpg http://api.xfoto.com.cn/photos/upload |
|
70 |
+# curl -X POST -F user=xxxxxxx -F session=xxxxxxx -F photo_id=xxxxxxx -F photo=@xxxxxxx.jpg http://api.pai.ai/photos/upload |
|
71 | 71 |
def upload_photo(request): |
72 | 72 |
lensman_id = request.POST.get('user', '') |
73 | 73 |
session_id = request.POST.get('session', '') |