通過項目來深入理解tornado(七):aiofiles實現異步文件上傳
前言
現在論壇需要新增一個功能,就是創建小組
數據表如下
models.py
from datetime import datetime from peewee import * from tornado_bbs.models import BaseModel from apps.users.models import User class CommunityGroup(BaseModel): creator = ForeignKeyField(User, verbose_name="創建者") name = CharField(max_length=100, null=True, verbose_name="名稱") category = CharField(max_length=20, verbose_name="分類", null=True) front_image = CharField(max_length=200, null=True, verbose_name="封面圖") desc = TextField(verbose_name="簡介") notice = TextField(verbose_name="公告") #小組的信息 member_nums = IntegerField(default=0, verbose_name="成員數") post_nums = IntegerField(default=0, verbose_name="帖子數") @classmethod def extend(cls): return cls.select(cls, User.id, User.nick_name).join(User) HANDLE_STATUS = ( ("agree", "同意"), ("refuse", "拒絕") ) class CommunityGroupMember(BaseModel): user = ForeignKeyField(User, verbose_name="用戶") community = ForeignKeyField(CommunityGroup, verbose_name="社區") status = CharField(choices=HANDLE_STATUS, max_length=10, null=True, verbose_name="處理狀態") handle_msg = CharField(max_length=200, null=True, verbose_name="處理內容") apply_reason = CharField(max_length=200, verbose_name="申請理由") handle_time = DateTimeField(default=datetime.now(), verbose_name="加入時間")
這里存在一個問題,就是peewee它沒有image字段或者file字段,所以后面驗證就需要自己來做了。
重頭戲來了
handler.py
from tornado_bbs.handler import BaseHandler from tools.auth_dec import authenticated from .forms import CommunityGroupForm import aiofiles import uuid from .models import CommunityGroup class GroupHandler(BaseHandler): async def get(self, *args, **kwargs): pass @authenticated async def post(self, *args, **kwargs): re_data = {} form = CommunityGroupForm(self.request.body_arguments) if form.validate(): # 需要自己做文件的驗證 files = self.request.files.get("front_image", None) if files: new_file='' for file in files: new_file = file['filename'] + uuid.uuid4().hex file_path = os.path.join(self.settings['media_path'], new_file) async with aiofiles.open(file_path, 'wb') as f: await f.write(file['body']) group = await self.application.objects.create(CommunityGroup, creator=self.current_user, name=form.name.data, categoru=form.category.data, front_image=new_file, desc=form.desc.data, notice=form.notice.data) re_data['id'] = group.id else: self.set_status(400) re_data['front_image'] = '請上傳圖片' else: self.set_status(400) for fields in form.errors: re_data[fields] = form.errrors[fields][0] self.finish(re_data)
總結:
首先,form = CommunityGroupForm(self.request.body_arguments)
這個里面因為有文件存在,所以不能用之前的form_json.# 另如果前端傳遞過來的是json數據。需要用self.request.body獲取並且需要decode(utf8)然后json.loads()
上傳的文件存放在self.request.files屬性里面,格式需要看前端怎么放
文件名字在file[filename]里,文件內容file[body]
最后就是aiofiles里,github里面的開源項目。
文件路徑需要用,項目路徑加上文件名稱,而項目路徑可以用os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
至此,文件上傳功能完成