|
# -*- coding: utf-8 -*-
import os
import shortuuid
from curtail_uuid import CurtailUUID
from django.conf import settings
from django.core.files.storage import default_storage
from django.db import transaction
from django.http import JsonResponse
from django.shortcuts import render
from rest_framework import viewsets
from TimeConvert import TimeConvert as tc
from account.models import LensmanInfo, UserInfo
from group.models import GroupInfo, GroupPhotoInfo, GroupUserInfo
from photo.models import PhotosInfo, UUIDInfo
from photo.serializers import PhotosInfoSerializer
from utils.error.errno_utils import PhotoStatusCode
from utils.error.response_utils import response
from utils.ip_utils import ip_addr
from utils.redis.rgroup import get_group_info, get_group_users_info, set_group_info, set_group_users_info
from utils.redis.rkeys import GROUP_LAST_PHOTO_PK
from utils.thumbnail_utils import make_thumbnail
from utils.watermark_utils import watermark_wrap
r = settings.REDIS_CACHE
def uuid_init(request):
"""
生成唯一标识
:param request:
:return:
"""
num = int(request.GET.get('num', 1000))
for i in xrange(num):
UUIDInfo.objects.create(uuid=CurtailUUID.uuid(UUIDInfo))
return JsonResponse({
'status': 200,
'message': u'UUID 更新成功',
'data': '',
})
# curl -X POST -F user=xxxxxxx -F num=100 http://api.pai.ai/uuid
@transaction.atomic
def uuid(request):
"""
获取唯一标识
:param request:
:return:
"""
lensman_id = request.POST.get('user', '')
num = int(request.POST.get('num', 100))
uuids = UUIDInfo.objects.select_for_update().filter(status=True)[:num]
for uuid in uuids:
uuid.lensman_id = lensman_id
uuid.status = False
uuid.save()
return JsonResponse({
'status': 200,
'message': u'获取唯一标识成功',
'data': [uuid.uuid for uuid in uuids],
})
# [How to do a PUT request with curl?](http://stackoverflow.com/questions/13782198/how-to-do-a-put-request-with-curl)
# Unfortunately, the -T is no substitute for -X PUT if you want to specify parameters with -d or -F.
# -T sends the content of a file via PUT. To achieve the GET after a redirect, add the parameter --location
#
# -F, --form <name=content>
# (HTTP) This lets curl emulate a filled-in form in which a user has pressed the submit button. This causes curl to POST data
# using the Content-Type multipart/form-data according to RFC 2388. This enables uploading of binary files etc. To force the
# 'content' part to be a file, prefix the file name with an @ sign. To just get the content part from a file, prefix the file
# name with the symbol <. The difference between @ and < is then that @ makes a file get attached in the post as a file upload,
# while the < makes a text field and just get the contents for that text field from a file.
#
# curl -X POST -F user=xxxxxxx -F session=xxxxxxx -F photo_id=xxxxxxx -F photo=@xxxxxxx.jpg http://api.pai.ai/photos/upload
def upload_photo(request):
"""
上传图片
:param request:
:return:
"""
lensman_id = request.POST.get('user', '')
session_id = request.POST.get('session', '')
photo_id = request.POST.get('photo_id', '')
photo = request.FILES.get('photo', '')
if not (lensman_id and session_id and photo):
return response(PhotoStatusCode.PARAMS_ERROR)
try:
LensmanInfo.objects.get(lensman_id=lensman_id)
except LensmanInfo.DoesNotExist:
return JsonResponse({
'status': 4000,
'message': u'摄影师不存在',
})
# photo_id = curtailUUID(PhotosInfo, 'photo_id')
_, extension = os.path.splitext(photo.name)
extension = extension or 'jpeg'
m_photo_path = 'photo/{uuid}{extension}'.format(uuid=shortuuid.uuid(), extension=extension)
if default_storage.exists(m_photo_path):
default_storage.delete(m_photo_path)
default_storage.save(m_photo_path, photo)
p_photo_path = 'photo/{uuid}{extension}'.format(uuid=shortuuid.uuid(), extension=extension)
watermark_wrap(
os.path.join(settings.MEDIA_ROOT, m_photo_path).replace('\\', '/'),
settings.WATERMARK_LOGO,
os.path.join(settings.MEDIA_ROOT, p_photo_path).replace('\\', '/')
)
photo, created = PhotosInfo.objects.get_or_create(
lensman_id=lensman_id,
session_id=session_id,
photo_id=photo_id,
p_photo_path=p_photo_path,
m_photo_path=m_photo_path,
)
return JsonResponse({
'status': 200,
'message': u'照片上传成功',
'data': photo.data,
})
def session_join_api(request):
"""
Session 详情
:param request:
:return:
"""
user_id = request.POST.get('user_id', '')
session_id = request.POST.get('session_id', '')
nickname = request.POST.get('nickname', '')
current_id = -1
# 判断 user_id 是否存在,如果不存在,则直接分配帐户
user, user_created = UserInfo.objects.get_or_create(user_id=user_id, defaults={
'user_id': CurtailUUID.uuid(UserInfo, 'user_id'),
'user_status': UserInfo.ASSIGN,
'assign_ip': ip_addr(request),
'assign_at': tc.utc_datetime(),
})
user_id = user.user_id
# 判断通过 session_id 创建的群组是否存在,如果不存在,则直接创建
group, group_created = GroupInfo.objects.get_or_create(session_id=session_id, defaults={
'group_id': CurtailUUID.uuid(GroupInfo, 'group_id'),
'admin_id': user_id,
'group_name': user.final_nickname,
'group_default_avatar': 0,
'group_from': GroupInfo.SESSION_GROUP,
'session_id': session_id,
})
group_id = group.group_id
# Redis 群组数据缓存
group_info = set_group_info(group) if group_created else get_group_info(group_id)
# 判断 group_id/user_id 的群组用户是否存在,如果不存在,则直接创建
group_user, group_user_created = GroupUserInfo.objects.get_or_create(group_id=group_id, user_id=user_id, defaults={
# 'current_id': int(r.get(GROUP_LAST_PHOTO_PK % group_id) or -1),
'current_id': current_id, # 通过扫描 session_id 二维码进群的用户,默认可以查看该群组所有照片
'nickname': nickname or user.final_nickname,
'avatar': user.avatar,
'admin': group_created,
'user_status': GroupUserInfo.PASSED,
'passed_at': tc.utc_datetime(),
})
# Redis 群组用户数据缓存
group_users = set_group_users_info(group) if group_user_created else get_group_users_info(group_id, user_id)
# 获取 Session 照片
photos = PhotosInfo.objects.filter(session_id=session_id)
#
if group_created:
for photo in photos:
photo_path = photo.p_photo_path
photo_thumbnail_path = photo_path.replace('.', '_thumbnail.')
photo_thumbnail2_path = photo_path.replace('.', '_thumbnail2.')
# 群组照片缩略图生成
# 双列: 540, 40-50K
photo_w, photo_h, photo_thumbnail_w, photo_thumbnail_h = make_thumbnail(
os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
os.path.join(settings.MEDIA_ROOT, photo_thumbnail_path).replace('\\', '/'),
settings.THUMBNAIL_MAX_WIDTH
)
# 单列: 1080, xx-100K
photo_w, photo_h, photo_thumbnail2_w, photo_thumbnail2_h = make_thumbnail(
os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
os.path.join(settings.MEDIA_ROOT, photo_thumbnail2_path).replace('\\', '/'),
settings.THUMBNAIL_MAX_WIDTH2
)
# 群组照片记录创建
group_photo = GroupPhotoInfo.objects.create(
group_id=group_id,
user_id=user_id,
nickname=user.final_nickname,
avatar=user.avatar,
photo_path=photo_path,
photo_w=photo_w,
photo_h=photo_h,
photo_thumbnail_path=photo_thumbnail_path,
photo_thumbnail_w=photo_thumbnail_w,
photo_thumbnail_h=photo_thumbnail_h,
photo_thumbnail2_path=photo_thumbnail2_path,
photo_thumbnail2_w=photo_thumbnail2_w,
photo_thumbnail2_h=photo_thumbnail2_h,
photo_from=GroupPhotoInfo.SESSION_GROUP,
session_id=photo.session_id,
lensman_id=photo.lensman_id,
lensman_photo_id=photo.photo_id,
)
# 设置群组最后一张照片PK
r.set(GROUP_LAST_PHOTO_PK % group_id, group_photo.pk)
# 获取从 current_id 到 now 的群组照片列表
group_photos = GroupPhotoInfo.objects.filter(
group_id=group_id,
status=True,
pk__gt=group_user.current_id,
).order_by(
'-pk'
)
latest_photo = group_photos.first()
return JsonResponse({
'status': 200,
'message': u'申请成功',
'data': {
'current_id': latest_photo and latest_photo.pk or current_id,
'photos': [photo.photo_info(user_id) for photo in group_photos],
'group_id': group_id,
'group': group_info,
'user_id': user_id,
'users': group_users,
}
})
def session_detail(request, session):
photos = PhotosInfo.objects.filter(session_id=session)
return render(request, 'photo/session_detail.html', {'photos': photos})
def photo_standard(request, photo):
photo = PhotosInfo.objects.get(photo_id=photo)
return render(request, 'photo/photo_detail.html', {'photo_url': photo.p_photo_url})
def photo_standard_api(request, photo):
photo = PhotosInfo.objects.get(photo_id=photo)
return JsonResponse({
'status': 200,
'message': u'获取照片详情成功',
'data': {
'photo': photo.detail,
}
})
def photo_medium(request, photo):
photo = PhotosInfo.objects.get(photo_id=photo)
return render(request, 'photo/photo_detail.html', {'photo_url': photo.m_photo_url})
def photo_large(request, photo):
photo = PhotosInfo.objects.get(photo_id=photo)
return render(request, 'photo/photo_detail.html', {'photo_url': photo.l_photo_url})
def photo_raw(request, photo):
photo = PhotosInfo.objects.get(photo_id=photo)
return render(request, 'photo/photo_detail.html', {'photo_url': photo.r_photo_url})
class PhotoInfoViewSet(viewsets.ModelViewSet):
queryset = PhotosInfo.objects.all().order_by('-pk')
serializer_class = PhotosInfoSerializer
|