@@ -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', '')
               |