-
Notifications
You must be signed in to change notification settings - Fork 8
refactor: migrate web framework from Flask to FastAPI #333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 5 commits
9da99af
728e53d
0c13e7f
7572e57
6fe3d87
a9ef4ee
01d4a35
ae1fd85
6e48f1a
4f40ca9
6bdcb3e
bc6d1aa
f42f781
8f4ac2a
dabdf0e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,65 +1,71 @@ | ||
| from datetime import datetime | ||
| from flask import Blueprint | ||
| from typing import Optional | ||
| from fastapi import APIRouter, Depends | ||
|
|
||
| from mongo import * | ||
| from mongo.utils import * | ||
| from .auth import * | ||
| from .auth import login_required | ||
| from .utils import * | ||
| from .schemas import CreateAnnouncementBody, UpdateAnnouncementBody, DeleteAnnouncementBody | ||
| from .course import * | ||
| from .course import course_router | ||
|
|
||
| __all__ = ['ann_api'] | ||
| __all__ = ['ann_router'] | ||
|
|
||
| ann_api = Blueprint('ann_api', __name__) | ||
| ann_router = APIRouter() | ||
|
|
||
|
|
||
| @ann_api.route('/', methods=['GET']) | ||
| @ann_api.route('/<ann_id>', methods=['GET']) | ||
| def get_sys_ann(ann_id=None): | ||
| public_name = Course.get_public().course_name | ||
| anns = Announcement.ann_list(None, public_name) | ||
| data = [{ | ||
| def _format_ann(an): | ||
| return { | ||
| 'annId': str(an.id), | ||
| 'title': an.title, | ||
| 'createTime': int(an.create_time.timestamp()), | ||
| 'updateTime': int(an.update_time.timestamp()), | ||
| 'creator': an.creator.info, | ||
| 'updater': an.updater.info, | ||
| 'markdown': an.markdown, | ||
| 'pinned': an.pinned | ||
| } for an in anns if ann_id == None or str(an.id) == ann_id] | ||
| 'pinned': an.pinned, | ||
| } | ||
|
|
||
|
|
||
| @ann_router.get('') | ||
| @ann_router.get('/{ann_id}') | ||
| def get_sys_ann(ann_id: Optional[str] = None): | ||
| public_name = Course.get_public().course_name | ||
| anns = Announcement.ann_list(None, public_name) | ||
| data = [ | ||
| _format_ann(an) for an in anns | ||
| if ann_id is None or str(an.id) == ann_id | ||
| ] | ||
| return HTTPResponse('Sys Ann bro', data=data) | ||
|
|
||
|
|
||
| @course_api.get('/<course_name>/ann') | ||
| @ann_api.get('/<course_name>/<ann_id>') | ||
| @login_required | ||
| def get_announcements(user, course_name=None, ann_id=None): | ||
| # Get an announcement list | ||
| @course_router.get('/{course_name}/ann') | ||
| def get_course_announcements(course_name: str, user=Depends(login_required)): | ||
| try: | ||
| anns = Announcement.ann_list(user.obj, course_name or 'Public') | ||
| anns = Announcement.ann_list(user.obj, course_name) | ||
| except (DoesNotExist, ValidationError): | ||
| return HTTPError('Cannot Access a Announcement', 403) | ||
| if anns is None: | ||
| return HTTPError('Announcement Not Found', 404) | ||
| data = [{ | ||
| 'annId': str(an.id), | ||
| 'title': an.title, | ||
| 'createTime': int(an.create_time.timestamp()), | ||
| 'updateTime': int(an.update_time.timestamp()), | ||
| 'creator': an.creator.info, | ||
| 'updater': an.updater.info, | ||
| 'markdown': an.markdown, | ||
| 'pinned': an.pinned | ||
| } for an in anns if ann_id is None or str(an.id) == ann_id] | ||
| data = [_format_ann(an) for an in anns] | ||
| return HTTPResponse('Announcement List', data=data) | ||
|
|
||
|
|
||
| @ann_api.post('/') | ||
| @login_required | ||
| @parse_body(CreateAnnouncementBody) | ||
| def create_announcement(user, body: CreateAnnouncementBody): | ||
| # Create a new announcement | ||
| @ann_router.get('/{course_name}/{ann_id}') | ||
| def get_ann_by_id(course_name: str, ann_id: str, user=Depends(login_required)): | ||
| try: | ||
| anns = Announcement.ann_list(user.obj, course_name) | ||
| except (DoesNotExist, ValidationError): | ||
| return HTTPError('Cannot Access a Announcement', 403) | ||
| if anns is None: | ||
| return HTTPError('Announcement Not Found', 404) | ||
| data = [_format_ann(an) for an in anns if str(an.id) == ann_id] | ||
| return HTTPResponse('Announcement List', data=data) | ||
|
Comment on lines
+42
to
+63
|
||
|
|
||
|
|
||
| @ann_router.post('') | ||
| def create_announcement(body: CreateAnnouncementBody, | ||
| user=Depends(login_required)): | ||
| try: | ||
| ann = Announcement.new_ann( | ||
| title=body.title, | ||
|
|
@@ -76,20 +82,17 @@ def create_announcement(user, body: CreateAnnouncementBody): | |
| return HTTPError('Failed to Create Announcement', 403) | ||
| data = { | ||
| 'annId': str(ann.id), | ||
| 'createTime': int(ann.create_time.timestamp()) | ||
| 'createTime': int(ann.create_time.timestamp()), | ||
| } | ||
| return HTTPResponse('Announcement Created', data=data) | ||
|
|
||
|
|
||
| @ann_api.put('/') | ||
| @login_required | ||
| @parse_body(UpdateAnnouncementBody) | ||
| def update_announcement(user, body: UpdateAnnouncementBody): | ||
| # Update an announcement | ||
| @ann_router.put('') | ||
| def update_announcement(body: UpdateAnnouncementBody, | ||
| user=Depends(login_required)): | ||
| ann = Announcement(body.ann_id) | ||
| if not ann: | ||
| return HTTPError('Announcement Not Found', 404) | ||
|
|
||
| course = Course(ann.course) | ||
| if not course.permission(user, Course.Permission.GRADE): | ||
| return HTTPError('Failed to Update Announcement', 403) | ||
|
|
@@ -102,23 +105,18 @@ def update_announcement(user, body: UpdateAnnouncementBody): | |
| pinned=body.pinned, | ||
| ) | ||
| except ValidationError as ve: | ||
| return HTTPError( | ||
| 'Failed to Update Announcement', | ||
| 400, | ||
| data=ve.to_dict(), | ||
| ) | ||
| return HTTPError('Failed to Update Announcement', | ||
| 400, | ||
| data=ve.to_dict()) | ||
| return HTTPResponse('Updated') | ||
|
|
||
|
|
||
| @ann_api.delete('/') | ||
| @login_required | ||
| @parse_body(DeleteAnnouncementBody) | ||
| def delete_announcement(user, body: DeleteAnnouncementBody): | ||
| # Delete an announcement | ||
| @ann_router.delete('') | ||
| def delete_announcement(body: DeleteAnnouncementBody, | ||
| user=Depends(login_required)): | ||
| ann = Announcement(body.ann_id) | ||
| if not ann: | ||
| return HTTPError('Announcement Not Found', 404) | ||
|
|
||
| course = Course(ann.course) | ||
| if not course.permission(user, Course.Permission.GRADE): | ||
| return HTTPError('Failed to Delete Announcement', 403) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'data': jsonable_encoder(exc.errors())Ref: https://fastapi.tiangolo.com/tutorial/handling-errors/#use-the-requestvalidationerror-body