diff --git a/app/api/v1/__init__.py b/app/api/v1/__init__.py index bcd220e..f2a9bd8 100644 --- a/app/api/v1/__init__.py +++ b/app/api/v1/__init__.py @@ -4,6 +4,7 @@ from app.api.v1.api import api from app.api.v1.auth import auth from app.api.v1.record import record from app.api.v1.user import user +from app.api.v1.diet import diet def create_v1(): @@ -12,6 +13,7 @@ def create_v1(): bp_v1.register_blueprint(auth, url_prefix='/auth') bp_v1.register_blueprint(record, url_prefix='/record') bp_v1.register_blueprint(user, url_prefix='/user') + bp_v1.register_blueprint(diet, url_prefix='/diet') return bp_v1 diff --git a/app/api/v1/api.py b/app/api/v1/api.py index ea0f138..b1db89c 100644 --- a/app/api/v1/api.py +++ b/app/api/v1/api.py @@ -7,22 +7,22 @@ from apiflask import APIBlueprint from flask import session from app import rpc -from app.api.v1.exception.api import ImageUploadError, UserInfoError, ImageNotFound -from app.api.v1.schema.api import ImageIn, ImagePreSignUrlOut, ImagePreSignUrlIn +from app.api.v1.exception.api import ImageUploadError, UserInfoError, ImageNotFound, DietCreationError +from app.api.v1.schema.api import ImageIn, ImagePreSignUrlOut, ImagePreSignUrlIn, DietImageIn from app.util.auth import login_required api = APIBlueprint('api', __name__) @api.post('/images') -@api.doc(summary='上传图片', description='上传图片') +@api.doc(summary='上传头像图片', description='上传头像图片') @api.input(ImageIn, location='files') @api.output(ImagePreSignUrlOut) @login_required -def upload_image(files_data): +def upload_avatar_image(files_data): f = files_data['image'] try: - result = rpc.storage.upload(file_name=str(session['user_id']+f'_{f.filename}'), + result = rpc.storage.upload(file_name=str(session['user_id'] + f'_{f.filename}'), file_binary=f.read(), bucket='bodyrecord', folder='avatar', @@ -49,6 +49,44 @@ def upload_image(files_data): raise ImageUploadError() +@api.post('/images/diet') +@api.doc(summary='上传食物图片', description='上传食物图片') +@api.input(DietImageIn, location='files') +@api.output(ImagePreSignUrlOut) +@login_required +def upload_diet_image(files_data): + f = files_data['image'] + category = files_data['category'] # 食物类别 + try: + result = rpc.storage.upload(file_name=str(session['user_id'] + f'_{f.filename}'), + file_binary=f.read(), + bucket='bodyrecord', + folder='diet', + app='bodyrecord') + except Exception as e: + raise ImageUploadError(extra_data={'error_docs': str(e)}) + + if result.get('status') and result['status'] == 'UPLOADED': + # 图片上传成功,处理业务逻辑 + try: + rpc.diet.add(session['user_id'], + category=category, + diet_image_id=result['_id']) + except Exception as e: + raise DietCreationError(extra_data={'error_docs': str(e)}) + + try: + presign_url = rpc.storage.get_presign_url(result['_id'], + 'bodyrecord', + bucket='bodyrecord') + except Exception as e: + raise ImageNotFound(extra_data={'error_docs': str(e)}) + + return {'image_presign_url': presign_url} + else: + raise ImageUploadError() + + @api.get('/images/presign_url') @api.input(ImagePreSignUrlIn, location='query') @api.output(ImagePreSignUrlOut) @@ -56,9 +94,9 @@ def upload_image(files_data): def get_image_presign_url(query_data): try: presign_url = rpc.storage.get_presign_url(query_data['avatar_id'], - 'bodyrecord', - bucket='bodyrecord', - expire_time=query_data.get('expire_time', 3600)) + 'bodyrecord', + bucket='bodyrecord', + expire_time=query_data.get('expire_time', 3600)) except Exception as e: raise ImageNotFound(extra_data={'error_docs': str(e)}) return {'image_presign_url': presign_url} diff --git a/app/api/v1/diet.py b/app/api/v1/diet.py new file mode 100644 index 0000000..9206f37 --- /dev/null +++ b/app/api/v1/diet.py @@ -0,0 +1,39 @@ +from apiflask import APIBlueprint +from flask import session + +from app import rpc +from app.api.v1.exception.diet import DietRecordNotFound +from app.api.v1.schema.diet import DietRecordsIn, DietRecordsOut, DietRecordOut + +from app.util.auth import login_required + +diet = APIBlueprint('diet', __name__) + + +@diet.get('/list') +@diet.doc(summary='查询食物记录列表', description='查询食物记录列表') +@diet.input(DietRecordsIn, location='query') +@diet.output(DietRecordsOut) +@login_required +def get_diet_records(query_data): + try: + sort = query_data.get('sort', '-create_time') + current_date = query_data.get('current_date', None) + results = rpc.diet.get_all_by_user(session['user_id'], + sort=sort, + current_date=current_date) + except Exception as e: + raise DietRecordNotFound(extra_data={'error_docs': str(e)}) + return {'records': results} + + +@diet.get('/') +@diet.doc(summary='查询单条食物记录', description='查询单条食物记录') +@diet.output(DietRecordOut) +@login_required +def get_diet_record(diet_id): + try: + result = rpc.diet.get_one(diet_id) + except Exception as e: + raise DietRecordNotFound(extra_data={'error_docs': str(e)}) + return result diff --git a/app/api/v1/exception/api.py b/app/api/v1/exception/api.py index 0d2fd2c..769d33f 100644 --- a/app/api/v1/exception/api.py +++ b/app/api/v1/exception/api.py @@ -11,6 +11,11 @@ class UserInfoError(HTTPError): message = '设置用户信息失败' +class DietCreationError(HTTPError): + status_code = 500 + message = '添加食物记录失败' + + class ImageNotFound(HTTPError): status_code = 404 message = '获取图片链接失败' diff --git a/app/api/v1/exception/diet.py b/app/api/v1/exception/diet.py new file mode 100644 index 0000000..6790e0b --- /dev/null +++ b/app/api/v1/exception/diet.py @@ -0,0 +1,6 @@ +from apiflask import HTTPError + + +class DietRecordNotFound(HTTPError): + status_code = 404 + message = '找不到用户对应的食物记录' \ No newline at end of file diff --git a/app/api/v1/record.py b/app/api/v1/record.py index ca815b8..3b7f771 100644 --- a/app/api/v1/record.py +++ b/app/api/v1/record.py @@ -4,7 +4,7 @@ from flask import session from app import rpc from app.api.v1.exception.record import AddBodyRecordError, BodyRecordNotFound, BodyRecordChartError from app.api.v1.schema.record import BodyRecordIn, BodyRecordOut, BodyRecordsOut, BodyRecordsIn, BodyRecordChartIn, \ - BodyRecordChartOut, BodyRecordIdIn + BodyRecordChartOut from app.util.auth import login_required record = APIBlueprint('record', __name__) diff --git a/app/api/v1/schema/api.py b/app/api/v1/schema/api.py index 25276c2..1bf55af 100644 --- a/app/api/v1/schema/api.py +++ b/app/api/v1/schema/api.py @@ -6,8 +6,13 @@ class ImageIn(Schema): image = File() +class DietImageIn(Schema): + image = File() + category = String() + + class ImagePreSignUrlIn(Schema): - avatar_id = String(required=True) + image_id = String(required=True) expire_time = Integer() @@ -15,3 +20,7 @@ class ImagePreSignUrlOut(Schema): image_presign_url = URL() +class ImageIdOut(Schema): + image_id = String() + + diff --git a/app/api/v1/schema/diet.py b/app/api/v1/schema/diet.py new file mode 100644 index 0000000..905aef3 --- /dev/null +++ b/app/api/v1/schema/diet.py @@ -0,0 +1,20 @@ +from apiflask import Schema +from apiflask import fields + + +class DietRecordsIn(Schema): + sort = fields.String() + current_date = fields.String() + + +class DietRecordOut(Schema): + diet_id = fields.String(attribute='_id') + category = fields.String() + diet_image_id = fields.String() + diet_image_url = fields.URL() + create_time = fields.String() + update_time = fields.String(allow_none=True) + + +class DietRecordsOut(Schema): + records = fields.List(fields.Nested(DietRecordOut)) \ No newline at end of file