def get_criteria_in_course(): data_format = get_criteria() data_format.update({ 'course_id': fields.Integer(attribute=lambda x: x.course_assoc.courses_id), 'active': fields.Boolean(attribute=lambda x: x.course_assoc.active), 'in_question': fields.Boolean(attribute=lambda x: x.course_assoc.in_question) }) return data_format
class InternList(AuthorizedResource): intern_obj = { 'id': fields.Integer, 'name': fields.String, 'email': fields.String, 'joined_at': fields.DateTime, 'last_activity': fields.DateTime, 'type': fields.Integer } get_response = { 'error': fields.Boolean(default=False), 'interns': fields.List( fields.Nested({ 'intern': fields.Nested(intern_obj), 'reported_questions': fields.Integer, 'questions_categorized': fields.Integer, 'questions_approved': fields.Integer, 'text_solutions_submitted': fields.Integer, 'text_solutions_approved': fields.Integer, 'video_solutions_submitted': fields.Integer, 'video_solutions_approved': fields.Integer, })), 'total': fields.Integer } post_response = { 'error': fields.Boolean(default=False), 'intern': fields.Nested(intern_obj) } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('page', type=int, default=1) parser.add_argument('limit', type=int, default=app.config['INTERN_LIST_LIMIT']) args = parser.parse_args() interns, total = Intern.get_list(args['page'], args['limit']) return {'interns': interns, 'total': total} @marshal_with(post_response) def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('email', type=str, required=True) parser.add_argument('password', type=str, required=True) args = parser.parse_args() intern = Intern.create(name=args['name'], email=args['email'], password=md5(args['password']).hexdigest()) welcome_admin_email_task.delay(args) return {'intern': intern}
class Teacher(AuthorizedResource): get_response = { 'error': fields.Boolean(default=False), 'teacher': fields.Nested({ 'teacher': fields.Nested(TeacherList.teacher_obj), 'questions_categorized': fields.Integer, 'questions_approved': fields.Integer, 'text_solutions_submitted': fields.Integer, 'text_solutions_approved': fields.Integer, 'video_solutions_submitted': fields.Integer, 'video_solutions_approved': fields.Integer, 'reported_resolved': fields.Integer }) } put_response = { 'error': fields.Boolean(default=False), 'teacher': fields.Nested(TeacherList.teacher_obj) } @marshal_with(get_response) def get(self, *args, **kwargs): teacher = TeacherModel.get(kwargs['id']) return {'teacher': teacher} @marshal_with(put_response) def put(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('email', type=str, required=True) parser.add_argument('password', type=str) parser.add_argument('subject_expert', type=str, required=True) parser.add_argument('specialization', type=str, required=True) parser.add_argument('qualification', type=str, required=True) args = parser.parse_args() teacher = TeacherModel.get(kwargs['id']) teacher.name = args['name'] teacher.email = args['email'] teacher.subject_expert = args['subject_expert'] teacher.specialization = args['specialization'] teacher.qualification = args['qualification'] if args['password'] is not None: teacher.password = md5(args['password']).hexdigest() try: db.session.commit() except IntegrityError: db.session.rollback() raise EmailAlreadyRegistered return {'teacher': teacher}
class Intern(AuthorizedResource): get_response = { 'error': fields.Boolean(default=False), 'intern': fields.Nested({ 'intern': fields.Nested(InternList.intern_obj), 'reported_questions': fields.Integer, 'questions_categorized': fields.Integer, 'questions_approved': fields.Integer, 'text_solutions_submitted': fields.Integer, 'text_solutions_approved': fields.Integer, 'video_solutions_submitted': fields.Integer, 'video_solutions_approved': fields.Integer, }) } put_response = { 'error': fields.Boolean(default=False), 'intern': fields.Nested(InternList.intern_obj) } @marshal_with(get_response) def get(self, *args, **kwargs): intern = InternModel.get(kwargs['id']) return {'intern': intern} @marshal_with(put_response) def put(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('email', type=str, required=True) parser.add_argument('password', type=str) args = parser.parse_args() intern = InternModel.query.get(kwargs['id']) if intern is None: raise InvalidInternId intern.name = args['name'] intern.email = args['email'] if args['password'] is not None: intern.password = md5(args['password']).hexdigest() try: db.session.commit() except IntegrityError: raise EmailAlreadyRegistered return {'intern': intern} def delete(self, id): return {'error': False}
class Institute(AuthorizedResource): response = { 'error': fields.Boolean(default=False), 'institute': fields.Nested(InstituteList.institute_obj) } @marshal_with(response) def get(self, *args, **kwargs): institute = InstituteModel.get(kwargs['id']) return {'institute': institute} @marshal_with(response) def put(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('email', type=str, required=True) parser.add_argument('password', type=str) parser.add_argument('location', type=str, required=True) parser.add_argument('username', type=str, required=True) parser.add_argument('mobile_no', type=str, required=True) parser.add_argument('logo', type=str) args = parser.parse_args() institute = InstituteModel.get(kwargs['id']) institute.name = args['name'] institute.email = args['email'] institute.location = args['location'] institute.username = args['username'] institute.mobile_no = args['mobile_no'] if args['password'] is not None: institute.password = md5(args['password']).hexdigest() if args['logo'] is not None: s3 = S3() mimetype, image_data = parse_base64_string(args['logo']) mimetype_parts = mimetype.split('/') if len(mimetype_parts) > 1 and mimetype_parts[-1] in app.config[ 'ACCEPTED_IMAGE_EXTENSIONS']: # if mimetype has an extension and the extension is in the accepted list then proceed with the upload content_type = mimetype_parts[-1] url = s3.upload(image_data, content_type) institute.logo_url = url else: raise UnAcceptableFileType try: db.session.commit() except IntegrityError as e: db.session.rollback() if 'email' in e.message: raise EmailAlreadyRegistered if 'username' in e.message: raise UsernameAlreadyRegistered if 'mobile_no' in e.message: raise MobileNoAlreadyRegistered raise e return {'institute': institute}
class Student(AuthorizedResource): student_obj = { 'id': fields.Integer, 'name': fields.String, 'target_year': fields.Integer, 'institute': fields.Integer, 'type': fields.Integer, 'mobile_no': fields.String, 'email': fields.String, 'plan_id': fields.Integer, } get_response = { 'error': fields.Boolean(default=False), 'student': fields.Nested(student_obj) } @marshal_with(get_response) def get(self, id): student = {} return {'student': student} def put(self, id): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('email', type=str, required=True) parser.add_argument('password', type=str) parser.add_argument('mobile_no', type=str, required=True) parser.add_argument('target_year', type=int, required=True) parser.add_argument('institute', type=int, required=True) parser.add_argument('plan_id', type=int) parser.add_argument('type', type=int, required=True) args = parser.parse_args() return {'id': 12}
class DataOperatorList(AuthorizedResource): operator_obj = { 'id': fields.Integer, 'name': fields.String, 'email': fields.String, 'joined_at': fields.DateTime, 'last_activity': fields.DateTime, 'type': fields.Integer } get_response = { 'error': fields.Boolean(default=False), 'data_operators': fields.List(fields.Nested({ 'data_operator': fields.Nested(operator_obj), 'questions_added': fields.Integer, 'text_solutions_added': fields.Integer, 'video_solutions_added': fields.Integer })), 'total': fields.Integer } post_response = { 'error': fields.Boolean(default=False), 'data_operator': fields.Nested(operator_obj) } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('page', type=int, default=1) parser.add_argument('limit', type=int, default=app.config['DATA_OPERATOR_LIST_LIMIT']) args = parser.parse_args() rows, total = DataOperator.get_list(args['page'], args['limit']) return {'data_operators': rows, 'total': total} @marshal_with(post_response) def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('email', type=str, required=True) parser.add_argument('password', type=str, required=True) args = parser.parse_args() data_operator = DataOperator.create(name=args['name'], email=args['email'], password=md5(args['password']).hexdigest()) welcome_admin_email_task.delay(args) return {'data_operator': data_operator}
class InstituteMockTest(AuthorizedResource): response = { 'error': fields.Boolean(default=False), 'mock_test': fields.Nested(InstituteMockTestList.mock_test_obj), 'questions': fields.List(fields.Nested(QuestionList.question_obj)) } @marshal_with(response) def get(self, *args, **kwargs): mock_test = MockTest.query.get(kwargs['id']) if mock_test is None: raise InvalidMockTestId pushed_batch_ids = [ p.batch_id for p in PushedMockTest.query.filter( PushedMockTest.mock_test_id == mock_test.id).all() ] batches = Batch.get_filtered(include_ids=pushed_batch_ids, institute_id=kwargs['user'].id) mock_test.batches_pushed_to = [{ 'id': b.id, 'name': b.name, 'class': b.clazz } for b in batches] question_ids = [] for sid, data in json.loads(mock_test.question_ids).items(): question_ids.extend(data['q_ids']) questions = Question.get_filtertered_list( include_question_ids=question_ids)['questions'] return {'mock_test': mock_test, 'questions': questions} @marshal_with(response) def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('batch_ids', type=comma_separated_ints_type, required=True) args = parser.parse_args() mock_test = MockTest.query.get(kwargs['id']) if mock_test is None: raise InvalidMockTestId batches = { b.id: b for b in Batch.get_filtered(institute_id=kwargs['user'].id) } new_batch_ids = args['batch_ids'][:] for p in PushedMockTest.query.filter( PushedMockTest.mock_test_id == mock_test.id, PushedMockTest.batch_id.in_(batches.keys())).all(): if p.batch_id in args['batch_ids']: new_batch_ids.remove(p.batch_id) for batch_id in new_batch_ids: p = PushedMockTest(mock_test_id=mock_test.id, batch_id=batch_id, pushed_at=datetime.datetime.utcnow()) db.session.add(p) db.session.commit() return {'error': False}
class StudentMockTestQuestions(AuthorizedResource): get_response = { 'error': fields.Boolean(default=False), 'mock_test': fields.Nested(MockTestList.mock_test_obj), 'subjects': fields.List( fields.Nested({ 'questions': fields.List(fields.Nested(QuestionList.question_obj)), 'subject_id': fields.Integer, 'order': fields.Integer, 'q_ids': fields.List(fields.Integer) })) } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('mock_test_id', type=int, required=True) args = parser.parse_args() mock_test_id = args['mock_test_id'] mock_test = MockTest.query.get(mock_test_id) if mock_test is None: raise InvalidMockTestId question_data = json.loads(mock_test.question_ids) question_ids = [] for subject_id, data in question_data.items(): data['subject_id'] = subject_id question_ids.extend(data['q_ids']) sorted_question_data = sorted(question_data.values(), key=lambda d: d['order']) questions = Question.get_filtertered_list( include_question_ids=question_ids)['questions'] """ for question in questions: print '--options--' print question.correct_options print '---$$$---' question.correct_options = None question.option_reasons = None question.text_solution = None question.video_solution_url = None question.similar_question_ids = None question.average_time = None """ questions = {q.id: q for q in questions} for subject in sorted_question_data: subject['questions'] = map(lambda q_id: questions[q_id], subject['q_ids']) return {'mock_test': mock_test, 'subjects': sorted_question_data}
class ReportedQuestionList(AuthorizedResource): report_obj = { 'question': fields.Nested(QuestionList.question_obj), 'report_id': fields.Integer } get_response = { 'error': fields.Boolean(default=False), 'reports': fields.List(fields.Nested(report_obj)), 'total': fields.Integer } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('categorized', type=int, default=1) # the next field will contain comma separated ontology node ids parser.add_argument('ontology', type=comma_separated_ints_type) parser.add_argument('nature', type=str, choices=app.config['QUESTION_NATURE'].keys()) parser.add_argument('type', type=str, choices=app.config['QUESTION_TYPE'].keys()) parser.add_argument('difficulty', type=str, choices=app.config['QUESTION_DIFFICULTY_LEVEL']) parser.add_argument('average_time', type=str, choices=map(int, app.config['QUESTION_AVERAGE_TIME'])) parser.add_argument('page', type=int, default=1) parser.add_argument('limit', type=int, default=app.config['REPORTED_QUESTION_LIST_LIMIT']) args = parser.parse_args() reports, total = ReportedQuestion.get(args['nature'], args['type'], args['difficulty'], args['average_time'], args['ontology'], args['page'], args['limit']) return {'reports': reports, 'total': total} def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('question_id', type=int, required=True) args = parser.parse_args() report = ReportedQuestion.create(kwargs['user_type'].id, kwargs['user'].id, args['question_id']) return {'report_id': report.id}
class InstituteStudentAnalysis(AuthorizedResource): class JSObject(fields.Raw): def format(self, value): return json.loads(value) attempted_mock_test_obj = { 'id': fields.Integer, 'pushed_mock_test_id': fields.Integer, 'mock_test_id': fields.Integer, 'score': fields.Float, 'answers': JSObject, 'analysis': JSObject, 'attempted_at': fields.String } attempted_mock_test = deepcopy( AttemptedMockTestList.attempted_mock_test_obj) attempted_mock_test['pdf_report_url'] = fields.String response = { 'error': fields.Boolean(default=False), 'attempted_mock_tests': fields.List(fields.Nested(attempted_mock_test_obj)), 'mock_tests': fields.List(fields.Nested(MockTestList.mock_test_obj)), 'questions': fields.List(fields.Nested(QuestionList.question_obj)), 'accuracy': fields.Float, 'speed': fields.Float, 'attempted_mock_test': fields.Nested(attempted_mock_test), 'mock_test': fields.Nested(MockTestList.mock_test_obj), } @marshal_with(response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('student_id', type=int, required=True) parser.add_argument('attempted_mock_test_id', type=int) args = parser.parse_args() # if no attempted mock test id provided return cumulative analysis if args['attempted_mock_test_id'] is None: return AttemptedMockTestList.get_cumulative_analysis( args['student_id'], kwargs['user'].id) else: return AttemptedMockTest.get_analysis( args['attempted_mock_test_id'])
class QuestionsFileUpload(AuthorizedResource): post_response = { 'error': fields.Boolean(default=False), 'archive_s3_key': fields.String } @marshal_with(post_response) def post(self, *args, **kwargs): parse = reqparse.RequestParser() parse.add_argument('file', type=str, required=True) args = parse.parse_args() # create a file object of the image mimetype, file_data = parse_base64_string(args['file']) archive_file = StringIO(file_data) print 'yahan pahuncha 1' # upload the file to s3 with a unique uuid key_name = str(uuid.uuid4()) + '.zip' conn = S3Connection(app.config['S3_ACCESS_KEY'], app.config['S3_SECRET']) bucket = conn.get_bucket(app.config['S3_UPLOAD_SET_ARCHIVES_BUCKET']) archive_s3 = Key(bucket) archive_s3.key = key_name archive_s3.content_type = 'application/zip' archive_s3.set_contents_from_string(archive_file.getvalue()) archive_s3.set_acl('public-read') print 'yahan pahuncha 2' # close the StringIO object archive_file.close() print 'yahan pahuncha 3' # return the name of the S3 key return {'archive_s3_key': archive_s3.key}
class Question(AuthorizedResource): @staticmethod def is_categorization_same(question, params): if question.nature == params['nature'] and question.type == params['type'] and question.difficulty == params['difficulty'] and \ question.average_time == params['average_time']: if question.ontology[-1] == params['ontology_id']: return True return False response = { 'error': fields.Boolean(default=False), 'question': fields.Nested(QuestionList.question_obj) } @marshal_with(response) def get(self, *args, **kwargs): return {'question': QuestionModel.get(kwargs['id'])} @marshal_with(response) def put(self, *args, **kwargs): parser = reqparse.RequestParser() # the next field will be present when a comprehension question is updated parser.add_argument('comprehension_text', type=unicode) # the next field will be present when a comprehension question is updated parser.add_argument('comprehension_id', type=int) parser.add_argument('ontology_id', type=int) parser.add_argument('nature', type=str) parser.add_argument('type', type=str) parser.add_argument('difficulty', type=str) parser.add_argument('average_time', type=int) parser.add_argument('content', type=unicode, required=True) parser.add_argument('options', type=options_json_type, required=True) parser.add_argument('text_solution', type=unicode) parser.add_argument('video_solution_url', type=str) parser.add_argument('text_solution_by', type=user_json_type) parser.add_argument('video_solution_by', type=user_json_type) parser.add_argument('proof_read_categorization', type=int, choices=[0, 1]) parser.add_argument('proof_read_text_solution', type=int, choices=[0, 1]) parser.add_argument('proof_read_video_solution', type=int, choices=[0, 1]) parser.add_argument('error_reported', type=str, choices=['0', '1']) args = parser.parse_args() question = QuestionModel.get(kwargs['id']) if question is None: raise InvalidQuestionId comprehension = None if args['comprehension_id'] is not None: # comprehension_id is present, just update the comprehension content if its present in request if args['comprehension_text'] is not None: comprehension = Comprehension.update( args['comprehension_id'], args['comprehension_text']) else: # comprehension_id is not present, create the comprehension object if comprehension content is present in request if args['comprehension_text'] is not None: comprehension = Comprehension.create( args['comprehension_text']) comprehension_id = comprehension.id if comprehension is not None else ( args['comprehension_id'] if args['comprehension_id'] is not None else None) status = question.status # if complete categorization submitted if QuestionList.is_categorization_complete(args): ontology_obj = Ontology.query.get(args['ontology_id']) # question was uncategorized if status['categorized'] == '0': # set categorization flag status['categorized'] = '1' status['proof_read_categorization'] = '1' # delete any previous category submission # CategorySubmission.query.filter_by(question_id=question.id).delete() # create a category submission that will be sent for proof reading CategorySubmission.create(kwargs['user_type'].id, kwargs['user'].id, question.id, ontology=ontology_obj.absolute_path, type=args['type'], nature=args['nature'], difficulty=args['difficulty'], average_time=args['average_time']) # question was categorized else: # if edited from proof_read_categorization if args['proof_read_categorization'] == 1: # set proof_read_categorization flag status['proof_read_categorization'] = '1' # if categorization has changed if not self.is_categorization_same(question, args): # reject any previous accepted category submissions and delete their approvals prev_submissions = CategorySubmission.query.filter( CategorySubmission.question_id == question.id, CategorySubmission.status == 'accepted').all() for s in prev_submissions: s.status = 'rejected' CategoryApproval.query.filter_by( submission_id=s.id).delete() # create a new accepted category submission cs = CategorySubmission.create( kwargs['user_type'].id, kwargs['user'].id, question.id, ontology=ontology_obj.absolute_path, type=args['type'], nature=args['nature'], difficulty=args['difficulty'], average_time=args['average_time'], status='accepted') else: # get the category submission for this question which has neither been accepted nor rejected cs = CategorySubmission.query.filter( CategorySubmission.question_id == question.id, CategorySubmission.status == None).first() # create category submission approval CategoryApproval.create(cs.id, kwargs['user_type'].id, kwargs['user'].id) # edited from anywhere except proof_read_categorization else: # if categorization has changed if not self.is_categorization_same(question, args): # delete any previous category submission and its corresponding approvals CategorySubmission.query.filter_by( question_id=question.id).delete() CategorySubmission.create( kwargs['user_type'].id, kwargs['user'].id, question.id, ontology=ontology_obj.absolute_path, type=args['type'], nature=args['nature'], difficulty=args['difficulty'], average_time=args['average_time']) # if question was already proof read categorized, then reset proof_read_categorization status['proof_read_categorization'] = '1' #if status['proof_read_categorization'] == '1': # status['proof_read_categorization'] = '0' # if incomplete categorization submitted else: status['categorized'] = '0' status['proof_read_categorization'] = '0' status['finalized'] = '0' # delete any previous category submission and its corresponding approvals CategorySubmission.query.filter_by( question_id=question.id).delete() text_solution_submitted_by_type, text_solution_submitted_by_id, text_solution_added_by_type, text_solution_added_by_id = [ None ] * 4 # if text solution is submitted if args['text_solution'] is not None: text_solution_submitted_by_type = args['text_solution_by']['type'] text_solution_submitted_by_id = args['text_solution_by']['id'] text_solution_added_by_type = kwargs['user_type'].id text_solution_added_by_id = kwargs['user'].id # question had no text solution if status['text_solution_added'] == '0': status['text_solution_added'] = '1' status['proof_read_text_solutions'] = '1' # delete any previous text solution submission and its corresponding approvals #SolutionSubmission.query.filter(SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'text').delete() # create a new text solution submission SolutionSubmission.create(text_solution_submitted_by_type, text_solution_submitted_by_id, question.id, 'text', args['text_solution']) # question had text solution else: # if came from proof_read_text_solution if args['proof_read_text_solution'] == 1: status['text_solution_added'] = '1' status['proof_read_text_solution'] = '1' # if text solution changed if QuestionModel.parse_content( args['text_solution']) != question.text_solution: # reject any previous accepted text solution submissions and delete their corresponding approvals prev_submissions = SolutionSubmission.query.filter( SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'text', SolutionSubmission.status == 'accepted').all() for s in prev_submissions: s.status = 'rejected' SolutionApproval.query.filter_by( submission_id=s.id).delete() # create a new text solution submission ss = SolutionSubmission.create( text_solution_submitted_by_type, text_solution_submitted_by_id, question.id, 'text', args['text_solution'], status='accepted') else: # get the text solution submission for this question which has neither been accepted nor rejected ss = SolutionSubmission.query.filter( SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'text', SolutionSubmission.status == None).first() # create category submission approval SolutionApproval.create(ss.id, kwargs['user_type'].id, kwargs['user'].id) # edited from anywhere except proof_read_categorization else: # if text solution changed if QuestionModel.parse_content( args['text_solution']) != question.text_solution: # delete any previous text solution submission and its corresponding approvals SolutionSubmission.query.filter( SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'text').delete() # create a new text solution submission SolutionSubmission.create( text_solution_submitted_by_type, text_solution_submitted_by_id, question.id, 'text', args['text_solution']) # if text solution was already proof read , then reset proof_read_text_solution status['proof_read_text_solution'] = '1' print 'Here here here here!!!' #if status['proof_read_text_solution'] == '1': # status['proof_read_text_solution'] = '0' # if no text solution submitted else: status['text_solution_added'] = '0' status['proof_read_text_solution'] = '0' status['finalized'] = '0' # delete any previous text solution submission and its corresponding approvals SolutionSubmission.query.filter( SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'text').delete() video_solution_submitted_by_type, video_solution_submitted_by_id, video_solution_added_by_type, video_solution_added_by_id = [ None ] * 4 # if video solution is submitted if args['video_solution_url'] is not None: video_solution_submitted_by_type = args['video_solution_by'][ 'type'] video_solution_submitted_by_id = args['video_solution_by']['id'] video_solution_added_by_type = kwargs['user_type'].id video_solution_added_by_id = kwargs['user'].id # question had no video solution if status['video_solution_added'] == '0': status['video_solution_added'] = '1' # delete any previous video solution submission and its corresponding approvals #SolutionSubmission.query.filter(SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'video').delete() # create a new solution submission SolutionSubmission.create(video_solution_submitted_by_type, video_solution_submitted_by_id, question.id, 'video', args['video_solution_url']) # question had video solution else: # if came from proof_read_video_solution if args['proof_read_video_solution']: status['video_solution_added'] = '1' status['proof_read_video_solution'] = '1' # if video solution changed if args['video_solution_url'] != question.video_solution_url: # reject any previous accepted text solution submissions and delete their corresponding approvals prev_submissions = SolutionSubmission.query.filter( SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'video', SolutionSubmission.status == 'accepted').all() for s in prev_submissions: s.status = 'rejected' SolutionApproval.query.filter_by( submission_id=s.id).delete() # create a new text solution submission ss = SolutionSubmission.create( video_solution_submitted_by_type, video_solution_submitted_by_id, question.id, 'video', args['video_solution_url'], status='accepted') else: # get the video solution submission for this question which has neither been accepted nor rejected ss = SolutionSubmission.query.filter( SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'video', SolutionSubmission.status == None).first() # create category submission approval SolutionApproval.create(ss.id, kwargs['user_type'].id, kwargs['user'].id) # edited from anywhere except proof_read_categorization else: # if video solution changed if args['video_solution_url'] != question.video_solution_url: # delete any previous video solution submission and its corresponding approvals SolutionSubmission.query.filter( SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'video').delete() # create a new video solution submission SolutionSubmission.create( video_solution_submitted_by_type, video_solution_submitted_by_id, question.id, 'video', args['video_solution_url']) # if text solution was already proof read , then reset proof_read_text_solution if status['proof_read_video_solution'] == '1': status['proof_read_video_solution'] = '0' # if no video solution submitted else: status['video_solution_added'] = '0' status['video_read_text_solution'] = '0' status['finalized'] = '0' # delete any previous video solution submission and its corresponding approvals SolutionSubmission.query.filter( SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'video').delete() if args['error_reported'] is not None: status['error_reported'] = args['error_reported'] if '0' not in (status['proof_read_categorization'], status['proof_read_text_solution'], status['proof_read_video_solution'], status['error_reported']): # question has been proof read in all 3 respects so its finalized status['finalized'] = '1' question.update(args['content'], status, comprehension_id=comprehension_id, ontology_id=args['ontology_id'], average_time=args['average_time'], nature=args['nature'], type=args['type'], difficulty=args['difficulty'], text_solution=args['text_solution'], video_solution_url=args['video_solution_url'], text_solution_by_type=text_solution_added_by_type, text_solution_by_id=text_solution_added_by_id, video_solution_by_type=video_solution_added_by_type, video_solution_by_id=video_solution_added_by_id, **args['options']) if args['error_reported'] is not None and args['error_reported'] == '0': report = ReportedQuestion.query.filter( ReportedQuestion.question_id == question.id, ReportedQuestion.is_resolved == False).first() report.is_resolved = True report.resolved_by_type = kwargs['user_type'].id report.resolved_by_id = kwargs['user'].id report.resolved_at = datetime.datetime.utcnow() db.session.commit() return {'question': question, 'error': False}
instance_fields = { 'id': fields.String, 'name': fields.String, 'provisioned_at': fields.DateTime, 'lifetime_left': fields.Integer, 'maximum_lifetime': fields.Integer, 'runtime': fields.Float, 'state': fields.String, 'to_be_deleted': fields.Boolean, 'error_msg': fields.String, 'username': fields.String, 'user_id': fields.String, 'blueprint': fields.String, 'blueprint_id': fields.String, 'cost_multiplier': fields.Float(default=1.0), 'can_update_connectivity': fields.Boolean(default=False), 'instance_data': fields.Raw, 'public_ip': fields.String, 'client_ip': fields.String(default='not set'), 'logs': fields.Raw, } instance_log_fields = { 'id': fields.String, 'instance_id': fields.String, 'log_type': fields.String, 'log_level': fields.String, 'timestamp': fields.Float, 'message': fields.String }
class StudentList(AuthorizedResource): student_obj = { 'id': fields.Integer, 'name': fields.String, 'email': fields.String, 'target_year': fields.Integer, 'institute': fields.Integer, 'type': fields.Integer, 'mobile_no': fields.String, 'city': fields.String, 'branches': fields.List(fields.String), 'target_exams': fields.List(fields.String), 'father_name': fields.String, 'father_mobile_no': fields.String, 'payment_plan_id': fields.String, 'registered_from': fields.String } get_response = { 'error': fields.Boolean(default=False), 'students': fields.List(fields.Nested(student_obj)), 'total': fields.Integer } post_response = { 'error': fields.Boolean(default=False), 'student': fields.Nested(student_obj) } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('type', type=int, default=0) parser.add_argument('institute', type=int, default=0) parser.add_argument('target_year', type=int, default=0) parser.add_argument('status', type=int, default=0) parser.add_argument('page', type=int, default=1) parser.add_argument('limit', type=int, default=app.config['STUDENT_LIST_LIMIT']) args = parser.parse_args() students, total = Student.get_list(args['page'], args['limit']) return {'students': students, 'total': total} @marshal_with(post_response) def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('email', type=str, required=True) parser.add_argument('password', type=str, required=True) parser.add_argument('mobile_no', type=str, required=True) parser.add_argument('target_year', type=int, required=True) parser.add_argument('city', type=str) parser.add_argument('area', type=str) parser.add_argument('branches', type=comma_separated_ints_type, required=True) parser.add_argument('target_exams', type=comma_separated_ints_type, required=True) parser.add_argument('father_name', type=str) parser.add_argument('father_mobile_no', type=str) args = parser.parse_args() student = Student.create(name=args['name'], email=args['email'], password=md5(args['password']).hexdigest(), mobile_no=args['mobile_no'], target_year=args['target_year'], city=args['city'], area=args['area'], branches=args['branches'], target_exams=args['target_exams'], father_name=args['father_name'], father_mobile_no=args['father_mobile_no']) return {'student': student}
"arrival_date_time": DateTime(attribute="end_date_time"), "base_arrival_date_time": DateTime(attribute="base_end_date_time"), "co2_emission": Co2Emission(), } cost = { 'value': fields.String(), 'currency': fields.String(), } fare = { 'total': NonNullNested(cost), 'found': fields.Boolean(), 'links': FareLinks(attribute="ticket_id") } journey = { 'duration': fields.Integer(), 'nb_transfers': fields.Integer(), 'departure_date_time': DateTime(), 'arrival_date_time': DateTime(), 'requested_date_time': DateTime(), 'sections': NonNullList(NonNullNested(section)), 'from': PbField(place, attribute='origin'), 'to': PbField(place, attribute='destination'), 'type': fields.String(), 'fare': NonNullNested(fare), 'tags': fields.List(fields.String),
# AttentionValue helpers class ParseAttentionValue(object): @staticmethod def parse(data): av = data['attentionvalue'] sti = av['sti'] if 'sti' in av else None lti = av['lti'] if 'lti' in av else None vlti = av['vlti'] if 'vlti' in av else None return sti, lti, vlti av_fields = { 'sti': fields.Integer(attribute='sti'), 'lti': fields.Integer(attribute='lti'), 'vlti': fields.Boolean(attribute='vlti') } # Atom helpers class FormatHandleValue(fields.Raw): def format(self, value): return value.value() class FormatHandleList(fields.Raw): def format(self, values): return [elem.h.value() for elem in values] class AtomListResponse(object):
'count': fields.Integer, } book_fields = { 'id': fields.Integer, 'isbn': fields.String, 'title': fields.String, 'subtitle': fields.String, 'authors': fields.String, 'translator': fields.String, 'bookValue': fields.String, 'thumbnail': fields.String, 'publishedDate': fields.String, 'collateral_value': fields.Integer, 'numbers': fields.Integer, 'hidden': fields.Boolean, 'can_borrow': fields.Boolean(attribute=lambda x: x.can_borrow()), 'can_borrow_number': fields.Integer(attribute=lambda x: x.can_borrow_number()), 'tags': fields.List(fields.Nested(tag_fields), attribute=lambda x: x.tags), 'uri': fields.String(attribute=lambda x: url_for('api.book', book_id=x.id, _external=True)), } book_list = { 'items': fields.List(fields.Nested(book_fields)), 'next': fields.String, 'prev': fields.String, 'total': fields.Integer, 'pages_count': fields.Integer, 'current_page': fields.Integer, 'per_page': fields.Integer, } library_fields = { 'id': fields.Integer,
response.append({"type": "note", "id": uris.note}) for value in display_info.notes: response.append({ "type": 'notes', "id": value.uri, 'value': value.note, 'internal': True }) return response instance_status = { "data_version": fields.Integer(), "end_production_date": fields.String(), "is_connected_to_rabbitmq": fields.Boolean(), "last_load_at": fields.String(), "last_rt_data_loaded": fields.String(), "last_load_status": fields.Boolean(), "kraken_version": fields.String(attribute="navitia_version"), "nb_threads": fields.Integer(), "publication_date": fields.String(), "start_production_date": fields.String(), "status": fields.String(), } instance_parameters = { 'scenario': fields.Raw(attribute='_scenario_name'), 'journey_order': fields.Raw, 'max_walking_duration_to_pt': fields.Raw, 'max_bike_duration_to_pt': fields.Raw,
class BatchList(AuthorizedResource): @classmethod def batch_timings(cls, data): """ Validate batch timing format. It should be ``h1:m1-h2:m2`` :param data: :return: """ timings = data.split('-') if len(timings) != 2: raise ValueError('Timing format incorrect') for timing in timings: try: hour, minute = timing.split(':') except Exception: raise ValueError('Timing format incorrect') try: hour, minute = int(hour), int(minute) except Exception: raise ValueError('Hour and minute should be integer') if not (0 <= hour <= 23 and 0 <= minute <= 59): raise ValueError('Out of range values for hour and minute') return data batch_obj = { 'id': fields.Integer, 'name': fields.String, 'on_weekdays': fields.Boolean, 'on_weekends': fields.Boolean, 'clazz': fields.String, 'target_year': fields.Integer, 'target_exam': fields.String, 'type': fields.String, 'other': fields.String, 'batch_timings': fields.String, 'institute_id': fields.Integer, 'status': fields.Integer } get_response = { 'error': fields.Boolean(default=False), 'batches': fields.List(fields.Nested(batch_obj)) } post_response = { 'error': fields.Boolean(default=False), 'batch': fields.Nested(batch_obj) } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('days', type=str, choices=['weekdays', 'weekends']) parser.add_argument('type', type=str, choices=app.config['BATCH_TYPE'].keys()) parser.add_argument('target_year', type=int) parser.add_argument('target_exam', type=str, choices=app.config['TARGET_EXAMS'].keys()) parser.add_argument('branch', type=str, choices=app.config['BATCH_FIELD'].keys()) parser.add_argument('status', type=int, default=-1) args = parser.parse_args() if args['branch'] is not None: args['branches'] = [ args['branch'], ] args.pop('branch', None) batches = Batch.get_filtered(institute_id=kwargs['user'].id, **args) return {'batches': batches} @marshal_with(post_response) def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('on_weekdays', type=int, required=True, choices=[0, 1]) parser.add_argument('on_weekends', type=int, required=True, choices=[0, 1]) parser.add_argument('clazz', type=str, choices=['11', '12']) parser.add_argument('target_year', type=int, required=True) parser.add_argument('target_exam', type=str, required=True, choices=app.config['TARGET_EXAMS'].keys()) parser.add_argument('type', type=str, required=True, choices=app.config['BATCH_TYPE'].keys()) parser.add_argument('other', type=str) parser.add_argument('batch_timings', type=self.__class__.batch_timings) args = parser.parse_args() batch = Batch.create(name=args['name'], on_weekdays=bool(args['on_weekdays']), on_weekends=bool(args['on_weekends']), clazz=args['clazz'], target_year=args['target_year'], target_exam=args['target_exam'], type=args['type'], other=args['other'], batch_timings=args['batch_timings'], institute_id=kwargs['user'].id) return {'batch': batch}
class AttemptedMockTest(AuthorizedResource): class JSObject(fields.Raw): def format(self, value): return json.loads(value) attempted_mock_test = deepcopy( AttemptedMockTestList.attempted_mock_test_obj) attempted_mock_test['pdf_report_url'] = fields.String get_response = { 'error': fields.Boolean(default=False), 'attempted_mock_test': fields.Nested(attempted_mock_test), 'mock_test': fields.Nested(MockTestList.mock_test_obj), 'questions': fields.List(fields.Nested(QuestionList.question_obj)), } @classmethod def get_percentile(cls, attempted_mock_test): # attempted mock test with same `mock_test_id` similar_tests = AttemptedMockTestModel.query.filter( AttemptedMockTestModel.mock_test_id == attempted_mock_test.mock_test_id).all() if len(similar_tests) > 0: similar_test_scores = [test.score for test in similar_tests] sorted_scores = sorted(similar_test_scores) scores_more, scores_less = filter( lambda s: s > attempted_mock_test.score, sorted_scores), filter(lambda s: s < attempted_mock_test.score, sorted_scores) if len(scores_more) == 0 and len(scores_less) == 0: return 0.0 else: return len(scores_less) * 100.0 / len(sorted_scores) @classmethod def get_rank_and_college(cls, attempted_mock_test, mock_test): past_exams = PastExamResult.query.filter_by( exam=mock_test.target_exam).order_by(PastExamResult.year.desc()) if past_exams is not None: last_exam = past_exams.first() if last_exam is not None: last_exam_data = json.loads(last_exam.data) #attempted_mock_test.analysis['last_year_cutoff'] = last_exam_data['cutoff'] marks_ranks = [[ map(int, marks_range.split('~')), map(int, rank_range.split('~')) ] for marks_range, rank_range in last_exam_data['marks_rank'].items()] obtained_marks_range = None closest_obtained_marks_range = None for item in marks_ranks: marks_low = item[0][0] marks_high = item[0][1] if marks_low <= attempted_mock_test.score <= marks_high: obtained_marks_range = [[marks_low, marks_high], item[1]] break else: if closest_obtained_marks_range is None: closest_obtained_marks_range = [[ marks_low, marks_high ], item[1]] else: if abs(attempted_mock_test.score - closest_obtained_marks_range[0][0]) > abs( attempted_mock_test.score - marks_low): closest_obtained_marks_range = [[ marks_low, marks_high ], item[1]] if obtained_marks_range is None: obtained_marks_range = closest_obtained_marks_range obtained_marks_range[1].reverse() expected_rank = '%s-%s' % (obtained_marks_range[1][0], obtained_marks_range[1][1]) ranks_colleges = [[map(int, rank_range.split('~')), colleges] for rank_range, colleges in last_exam_data['rank_college'].items()] ranks_colleges = sorted(ranks_colleges, key=lambda x: int(x[0][0])) obtained_rank_range = None closest_obtained_rank_range = None for item in ranks_colleges: rank_low = item[0][0] rank_high = item[0][1] if rank_low <= obtained_marks_range[1][ 0] and obtained_marks_range[1][1] <= rank_high: obtained_rank_range = [[rank_low, rank_high], item[1]] break else: if obtained_marks_range[1][0] <= rank_high: if closest_obtained_rank_range is None: closest_obtained_rank_range = [[ rank_low, rank_high ], item[1]] else: if rank_low <= obtained_marks_range[1][ 0] and obtained_marks_range[1][ 1] > rank_high: if (obtained_marks_range[1][0] - rank_low ) > ( obtained_marks_range[1][0] - closest_obtained_rank_range[0][0]): closest_obtained_rank_range = [[ rank_low, rank_high ], item[1]] if rank_low > obtained_marks_range[1][ 0] and obtained_marks_range[1][ 1] <= rank_high: if (rank_high - obtained_marks_range[1][1] ) > ( obtained_marks_range[1][1] - closest_obtained_rank_range[0][1]): closest_obtained_rank_range = [[ rank_low, rank_high ], item[1]] if obtained_rank_range is None and closest_obtained_rank_range is not None: obtained_rank_range = closest_obtained_rank_range if obtained_rank_range is None and closest_obtained_rank_range is None: obtained_rank_range = [[], ['No colleges expected']] expected_colleges = obtained_rank_range[1] return expected_rank, expected_colleges @staticmethod def get_analysis(attempted_mock_test_id): attempted_mock_test = AttemptedMockTestModel.query.get( attempted_mock_test_id) if attempted_mock_test is None: raise InvalidAttemptedMockTestId mock_test = MockTest.query.get(attempted_mock_test.mock_test_id) if mock_test is None: raise InvalidMockTestId if attempted_mock_test.answers is None: return {'error': True, 'message': 'No answers yet'} attempted_mock_test.analysis = json.loads(attempted_mock_test.analysis) attempted_mock_test.analysis[ 'percentile'] = AttemptedMockTest.get_percentile( attempted_mock_test) attempted_mock_test.analysis['cutoff'] = mock_test.cutoff rank_colleges = AttemptedMockTest.get_rank_and_college( attempted_mock_test, mock_test) if rank_colleges is not None: attempted_mock_test.analysis[ 'expected_rank'], attempted_mock_test.analysis[ 'expected_colleges'] = rank_colleges attempted_mock_test.analysis = json.dumps(attempted_mock_test.analysis) question_data = json.loads(mock_test.question_ids) question_ids = [] for subject_id, data in question_data.items(): data['subject_id'] = subject_id question_ids.extend(data['q_ids']) questions = Question.get_filtertered_list( include_question_ids=question_ids)['questions'] return { 'attempted_mock_test': attempted_mock_test, 'mock_test': mock_test, 'questions': questions } @marshal_with(get_response) def get(self, *args, **kwargs): attempted_mock_test_id = kwargs['id'] return self.get_analysis(attempted_mock_test_id)
class QuestionUploadSetList(AuthorizedResource): mock_test_obj = { 'name': fields.String } upload_set_obj = { 'id': fields.Integer, 'name': fields.String, 'errors_exist': fields.Boolean, 'mock_test_id': fields.Integer, 'mock_test': fields.Nested(mock_test_obj), 'questions_added': fields.Boolean, } get_response = { 'total': fields.Integer, 'error': fields.Boolean(default=False), 'upload_sets': fields.List(fields.Nested(upload_set_obj)), } post_response = { 'error': fields.Boolean(default=False), 'upload_set': fields.Nested(upload_set_obj) } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('page', type=int, default=1) parser.add_argument('limit', type=int, default=app.config['UPLOAD_SET_LIST_LIMIT']) args = parser.parse_args() # get a list of all the upload sets in the DB (without the questions) upload_set_pag_obj = QuestionUploadSet.query.filter().order_by(QuestionUploadSet.created_at.desc()).paginate(args['page'], args['limit']) upload_sets = upload_set_pag_obj.items total = upload_set_pag_obj.total # return a list of tests return {'upload_sets': upload_sets, 'total': total} @marshal_with(post_response) def post(self, *args, **kwargs): parse = reqparse.RequestParser() parse.add_argument('name', type=str, required=True) parse.add_argument('archive_key', type=str, required=True) parse.add_argument('mock_test_id', type=str, required=True) args = parse.parse_args() parse_upload_set_async.delay(args['name'], args['archive_key'], args['mock_test_id']) print 'this is done' return 'this is good shit' #print 'Checking S3 key' # check if the s3 key exists conn = S3Connection(app.config['S3_ACCESS_KEY'], app.config['S3_SECRET']) bucket = conn.get_bucket(app.config['S3_UPLOAD_SET_ARCHIVES_BUCKET']) archive_s3 = bucket.get_key(args['archive_key']) if not archive_s3: raise ArchiveS3KeyDoesNotExist #print 'S3 key checked' #print 'Checking mock test' # check if the mock test is open and has no questions mock_test_id = args['mock_test_id'] mock_test = MockTest.query.get(mock_test_id) if not mock_test: raise InvalidMockTestId if not mock_test.question_ids is None: raise QuestionUploadSetMockSetNotEmpty #print 'Mock test checked' #print 'Getting contents from S3' # parse the paper and store it in json archive = StringIO() archive_s3.get_contents_to_file(archive) #print 'Contents from S3 got' #print 'parsing questions' parsed_questions = parse_paper(archive) #print 'questions parsed' # check the parsed questions for any `overall` errors. if there are then don't proceed if parsed_questions['is_overall_error']: error_message = '\n'.join([ exc.message for exc in parsed_questions['overall_errors'] ]) raise OverallQuestionParsingError(error_message) # check if any errors exist or not errors = False try: check_if_errors_exist_in_parsed_questions(parsed_questions) except Exception as e: errors = True # store the parsed questions in the DB upload_set = QuestionUploadSet.create( name=args['name'], errors_exist=errors, mock_test_id=mock_test.id, parsed_questions=ExceptionJSONEncoder().encode(parsed_questions['questions']), parsed_comprehensions=ExceptionJSONEncoder().encode(parsed_questions['comprehensions']) ) return {'upload_set': upload_set}
class QuestionList(AuthorizedResource): @staticmethod def is_categorization_complete(params): if None not in (params['nature'], params['type'], params['difficulty'], params['average_time']): # All required attributes present if params['ontology_id'] is not None and Ontology.is_leaf_node( params['ontology_id']): # Ontology is complete since leaf node. So consider it categorized return True return False question_obj = { 'id': fields.Integer, 'status': fields.Nested({ 'categorized': fields.String, 'proof_read_categorization': fields.String, 'text_solution_added': fields.String, 'video_solution_added': fields.String, 'proof_read_text_solution': fields.String, 'proof_read_video_solution': fields.String, 'finalized': fields.String, 'error_reported': fields.String }), 'content': fields.String, 'ontology': fields.List(fields.Integer), 'type': fields.String, 'difficulty': fields.String, 'nature': fields.String, 'average_time': fields.String, 'text_solution': fields.String, 'video_solution_url': fields.String, 'text_solution_by_type': fields.Integer(default=None), 'text_solution_by_id': fields.Integer(default=None), 'video_solution_by_type': fields.Integer(default=None), 'video_solution_by_id': fields.Integer(default=None), 'all_options': fields.List(fields.String), 'correct_options': fields.List(fields.Integer), 'option_reasons': fields.List(fields.String), 'comprehension': fields.Nested({ 'id': fields.Integer(default=None), 'content': fields.String }), 'similar_question_ids': fields.List(fields.Integer), } get_response = { 'error': fields.Boolean(default=False), 'questions': fields.List(fields.Nested(question_obj)), 'total': fields.Integer } post_response = { 'error': fields.Boolean(default=False), 'question': fields.Nested(question_obj) } common_parser = reqparse.RequestParser() common_parser.add_argument('nature', type=str, choices=app.config['QUESTION_NATURE'].keys()) common_parser.add_argument('type', type=str, choices=app.config['QUESTION_TYPE'].keys()) common_parser.add_argument('difficulty', type=str, choices=app.config['QUESTION_DIFFICULTY_LEVEL']) common_parser.add_argument('average_time', type=int, choices=map( int, app.config['QUESTION_AVERAGE_TIME'])) @marshal_with(get_response) def get(self, *args, **kwargs): parser = self.common_parser.copy() parser.add_argument('categorized', type=str, choices=['0', '1']) parser.add_argument('proof_read_categorization', type=str, choices=['0', '1']) parser.add_argument('proof_read_text_solution', type=str, choices=['0', '1']) parser.add_argument('proof_read_video_solution', type=str, choices=['0', '1']) parser.add_argument('finalized', type=str, choices=['0', '1']) parser.add_argument('error_reported', type=str, choices=['0', '1']) # this contains comma separated ontology node ids parser.add_argument('ontology', type=comma_separated_ints_type) parser.add_argument('ontology_id', type=int) parser.add_argument('is_comprehension', type=int, choices=[0, 1]) parser.add_argument('text_solution_added', type=int, choices=[0, 1]) parser.add_argument('video_solution_added', type=int, choices=[0, 1]) parser.add_argument('exclude_question_ids', type=comma_separated_ints_type) parser.add_argument('include_question_ids', type=comma_separated_ints_type) parser.add_argument('page', type=int, default=1) parser.add_argument('limit', type=int, default=app.config['QUESTION_BANK_LIST_LIMIT']) args = parser.parse_args() if args['ontology_id'] is not None and args['ontology'] is None: ontology_obj = Ontology.query.get(args['ontology_id']) if ontology_obj is not None: args['ontology'] = ontology_obj.absolute_path return Question.get_filtertered_list( nature=args['nature'], type=args['type'], difficulty=args['difficulty'], average_time=args['average_time'], categorized=args['categorized'], proof_read_categorization=args['proof_read_categorization'], proof_read_text_solution=args['proof_read_text_solution'], proof_read_video_solution=args['proof_read_video_solution'], finalized=args['finalized'], error_reported=args['error_reported'], text_solution_added=args['text_solution_added'], video_solution_added=args['video_solution_added'], ontology=args['ontology'], is_comprehension=args['is_comprehension'], exclude_question_ids=args['exclude_question_ids'], include_question_ids=args['include_question_ids'], page=args['page'], limit=args['limit']) @marshal_with(post_response) def post(self, *args, **kwargs): parser = self.common_parser.copy() # the next field will be present when the first question of a comprehension is added parser.add_argument('comprehension_text', type=unicode) # the next field will be present when question of an already created comprehension is added parser.add_argument('comprehension_id', type=int) parser.add_argument('ontology_id', type=int) parser.add_argument('content', type=unicode, required=True) parser.add_argument('options', type=options_json_type, required=True) parser.add_argument('text_solution', type=unicode) parser.add_argument('video_solution_url', type=str) parser.add_argument('text_solution_by', type=user_json_type) parser.add_argument('video_solution_by', type=user_json_type) args = parser.parse_args() comprehension = None if args['comprehension_id'] is not None: # comprehension_id is present, just update the comprehension content if its present in request if args['comprehension_text'] is not None: comprehension = Comprehension.update( args['comprehension_id'], args['comprehension_text']) else: # comprehension_id is not present, create the comprehension object if comprehension content if its present in request if args['comprehension_text'] is not None: comprehension = Comprehension.create( args['comprehension_text']) comprehension_id = comprehension.id if comprehension is not None else ( args['comprehension_id'] if args['comprehension_id'] is not None else None) status = { # keeping string values of 0 and 1 because postgres hstore needs keys and values as text 'categorized': '0', 'proof_read_categorization': '0', 'text_solution_added': '1' if args['text_solution'] is not None else '0', 'video_solution_added': '1' if args['video_solution_url'] is not None else '0', 'proof_read_text_solution': '0', 'proof_read_video_solution': '0', 'finalized': '0', 'error_reported': '0' } # If question is categorized if self.is_categorization_complete(args): status['categorized'] = '1' status['proof_read_categorization'] = '1' text_solution_submitted_by_type, text_solution_submitted_by_id, text_solution_added_by_type, text_solution_added_by_id = [ None ] * 4 if args['text_solution'] is not None: status['text_solution_added'] = '1' status['proof_read_text_solution'] = '1' text_solution_submitted_by_type = args['text_solution_by']['type'] text_solution_submitted_by_id = args['text_solution_by']['id'] text_solution_added_by_type = kwargs['user_type'].id text_solution_added_by_id = kwargs['user'].id video_solution_submitted_by_type, video_solution_submitted_by_id, video_solution_added_by_type, video_solution_added_by_id = [ None ] * 4 if args['video_solution_url'] is not None: status['video_solution_added'] = '1' status['proof_read_video_solution'] = '1' video_solution_submitted_by_type = args['video_solution_by'][ 'type'] video_solution_submitted_by_id = args['video_solution_by']['id'] video_solution_added_by_type = kwargs['user_type'].id video_solution_added_by_id = kwargs['user'].id question = Question.create( content=args['content'], status=status, comprehension_id=comprehension_id, ontology_id=args['ontology_id'], average_time=args['average_time'], nature=args['nature'], type=args['type'], difficulty=args['difficulty'], text_solution=args['text_solution'], video_solution_url=args['video_solution_url'], text_solution_by_type=text_solution_added_by_type if args['text_solution_by'] is not None else None, text_solution_by_id=text_solution_added_by_id if args['text_solution_by'] is not None else None, video_solution_by_type=video_solution_added_by_type if args['video_solution_by'] is not None else None, video_solution_by_id=video_solution_added_by_id if args['video_solution_by'] is not None else None, created_by_type=kwargs['user_type'].id, created_by_id=kwargs['user'].id, **args['options']) if status['categorized'] == '1': # Question is categorized. Submit it for approval ontology_obj = Ontology.query.get(args['ontology_id']) # Do a category submission so it can be verified by teacher CategorySubmission.create(kwargs['user_type'].id, kwargs['user'].id, question.id, ontology=ontology_obj.absolute_path, type=args['type'], nature=args['nature'], difficulty=args['difficulty'], average_time=args['average_time']) if args['text_solution'] is not None: # Text solution is provided. Do a solution submission so it can be verified by teacher SolutionSubmission.create(text_solution_submitted_by_type, text_solution_submitted_by_id, question.id, 'text', args['text_solution']) if args['video_solution_url'] is not None: # Video solution is provided. Do a solution submission so it can be verified by teacher SolutionSubmission.create(video_solution_submitted_by_type, video_solution_submitted_by_id, question.id, 'video', args['video_solution_url']) return { 'comprehension_id': comprehension_id, 'question': question, 'error': False }
class InstituteStudent(AuthorizedResource): student_obj = deepcopy(InstituteStudentList.student_obj) student_obj['mock_tests'] = fields.List( fields.Nested({ 'id': fields.Integer, 'name': fields.String, 'attempted': fields.Boolean })) response = { 'error': fields.Boolean(default=False), 'student': fields.Nested(student_obj), } @marshal_with(response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('profile', type=int, choices=[0, 1], default=0) args = parser.parse_args() student = Student.get(kwargs['id']) batch_ids = [ sb.batch_id for sb in StudentBatches.query.filter( StudentBatches.student_id == student.id, StudentBatches.left_at == None).all() ] batches = Batch.get_filtered(include_ids=batch_ids, institute_id=kwargs['user'].id) student.batches = [{'id': b.id, 'name': b.name} for b in batches] if args['profile'] == 1: pushed_mock_test_ids = { p.id: p.mock_test_id for p in PushedMockTest.query.filter( PushedMockTest.batch_id.in_([b.id for b in batches])).all() } mock_tests = { m.id: m for m in MockTest.query.filter( MockTest.id.in_(pushed_mock_test_ids.values())) } amts = AttemptedMockTest.query.filter( AttemptedMockTest.student_id == student.id, AttemptedMockTest.pushed_mock_test_id.in_( pushed_mock_test_ids.keys())).all() attempted_mock_test_ids = {amt.mock_test_id for amt in amts} student.mock_tests = [] seen_mock_test_ids = set() for pushed_id, mock_test_id in pushed_mock_test_ids.items(): mt = { 'id': mock_test_id, 'name': mock_tests[mock_test_id].name, 'attempted': False } for amt in amts: if pushed_id == amt.pushed_mock_test_id: mt['attempted'] = True break # if current mock test is not attempted if mt['attempted'] is False: # a similar attempted mock test exists then dont push this entry into the result if mock_test_id in attempted_mock_test_ids: continue # if similar mock test has already been pushed into the result if mock_test_id in seen_mock_test_ids: continue student.mock_tests.append(mt) seen_mock_test_ids.add(mock_test_id) return {'student': student} @marshal_with(response) def put(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('password', type=str) parser.add_argument('mobile_no', type=str, required=True) parser.add_argument('city', type=str) parser.add_argument('area', type=str) parser.add_argument('pin', type=str) parser.add_argument('school', type=str) parser.add_argument('ntse_score', type=float) parser.add_argument('roll_no', type=str) parser.add_argument('father_name', type=str) parser.add_argument('father_mobile_no', type=str) parser.add_argument('father_email', type=str) parser.add_argument('batch_ids', type=comma_separated_ints_type, required=True) args = parser.parse_args() student = Student.get(kwargs['id']) if args['password'] is not None: student.password = md5(args['password']).hexdigest() student.name = args['name'] student.mobile_no = args['mobile_no'] student.city = args['city'] student.area = args['area'] student.pin = args['pin'] student.school = args['school'] student.ntse_score = args['ntse_score'] student.roll_no = args['roll_no'] student.father_name = args['father_name'] student.father_mobile_no = args['father_mobile_no'] student.father_email = args['father_email'] unow = datetime.datetime.utcnow() # new batches that the student may join. ids from this will be removed in a loop later new_batch_ids = args['batch_ids'][:] for sb in StudentBatches.query.filter( StudentBatches.student_id == student.id).all(): # if any old batch_id not in newly supplied batch ids then student will leave that batch if sb.batch_id not in args['batch_ids']: sb.left_at = unow # old batch_id also in newly supplied batch ids so remove this batch_id from new_batch_ids else: new_batch_ids.remove(sb.batch_id) # if student rejoining if sb.left_at is not None: sb.left_at = None target_exams = set() target_year = None batches = Batch.get_filtered(include_ids=args['batch_ids']) engineering_exams = {'1', '2', '3'} medical_exams = {'4', '5'} for batch in batches: if batch.target_exam in engineering_exams: target_exams.update(engineering_exams) if batch.target_exam in medical_exams: target_exams.update(medical_exams) if target_year is None or target_year > batch.target_year: target_year = batch.target_year # if a new batch id encountered if batch.id in new_batch_ids: sb = StudentBatches(batch_id=batch.id, student_id=student.id, joined_at=datetime.datetime.utcnow()) db.session.add(sb) branches = [] if len(target_exams.intersection(engineering_exams)) > 0: branches.append('1') if len(target_exams.intersection(medical_exams)) > 0: branches.append('2') student.target_year = target_year student.target_exams = list(target_exams) student.branches = branches db.session.commit() student.batches = [{'id': b.id, 'name': b.name} for b in batches] return {'student': student}
class Batch(AuthorizedResource): response = { 'error': fields.Boolean(default=False), 'batch': fields.Nested(BatchList.batch_obj), } @marshal_with(response) def get(self, *args, **kwargs): batch = BatchModel.get(kwargs['id']) return {'batch': batch} @marshal_with(response) def put(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('on_weekdays', type=int, required=True, choices=[0, 1]) parser.add_argument('on_weekends', type=int, required=True, choices=[0, 1]) parser.add_argument('clazz', type=str, choices=['11', '12']) parser.add_argument('target_year', type=int, required=True) parser.add_argument('target_exam', type=str, required=True, choices=app.config['TARGET_EXAMS'].keys()) parser.add_argument('type', type=str, required=True, choices=app.config['BATCH_TYPE'].keys()) parser.add_argument('other', type=str) parser.add_argument('batch_timings', type=BatchList.batch_timings) parser.add_argument('status', type=int) args = parser.parse_args() batch = BatchModel.get(kwargs['id']) if args['status'] is not None and args['status'] == 1: batch.status = 1 else: batch.on_weekdays = bool(args['on_weekdays']) batch.on_weekends = bool(args['on_weekends']) if args['clazz'] is not None: batch.clazz = args['clazz'] batch.target_year = args['target_year'] batch.target_exam = args['target_exam'] batch.type = args['type'] if args['other'] is not None: batch.other = args['other'] if args['batch_timings'] is not None: batch.batch_timings = args['batch_timings'] db.session.commit() return {'batch': batch} def delete(self, *args, **kwargs): sbs = StudentBatches.query.filter( StudentBatches.batch_id == kwargs['id'], StudentBatches.left_at == None).count() if sbs > 0: raise BatchNotEmpty batch = BatchModel.get(kwargs['id']) batch.status = 0 db.session.commit() return {'error': False}
class SimilarQuestions(AuthorizedResource): get_response = { 'error': fields.Boolean(default=False), 'questions': fields.List(fields.Nested(QuestionList.question_obj)), 'total': fields.Integer } @marshal_with(get_response) def get(self, *args, **kwargs): """ Get questions questions not similar to the given question id :param args: :param kwargs: :return: """ parser = reqparse.RequestParser() parser.add_argument('nature', type=str, choices=app.config['QUESTION_NATURE'].keys()) parser.add_argument('type', type=str, choices=app.config['QUESTION_TYPE'].keys()) parser.add_argument('difficulty', type=str, choices=app.config['QUESTION_DIFFICULTY_LEVEL']) parser.add_argument('average_time', type=int, choices=map(int, app.config['QUESTION_AVERAGE_TIME'])) # this contains comma separated ontology node ids parser.add_argument('ontology', type=comma_separated_ints_type) parser.add_argument('question_id', type=int) parser.add_argument('offset', type=int, default=0) args = parser.parse_args() if args['question_id'] is None: exprs = [ Question.is_similarity_marked == False, Question.status['categorized'] == '1' ] if args['nature'] is not None: exprs.append(Question.nature == args['nature']) if args['type'] is not None: exprs.append(Question.type == args['type']) if args['difficulty'] is not None: exprs.append(Question.difficulty == args['difficulty']) if args['average_time'] is not None: exprs.append(Question.average_time == args['average_time']) if args['ontology'] is not None: exprs.append(Question.ontology == args['ontology']) question = Question.query.filter(*exprs).offset( args['offset']).first() if question is None: return {'questions': [], 'total': 0} else: other_questions = Question.get_filtertered_list( nature=args['nature'], type=args['type'], difficulty=args['difficulty'], average_time=args['average_time'], ontology=args['ontology'], categorized='1', exclude_question_ids=[ question.id, ]) if other_questions['total'] == 0: skip = args['offset'] + 1 while question is not None: question = Question.query.filter( *exprs).offset(skip).first() if question is None: return {'questions': [], 'total': 0} other_questions = Question.get_filtertered_list( nature=args['nature'], type=args['type'], difficulty=args['difficulty'], average_time=args['average_time'], ontology=args['ontology'], categorized='1', exclude_question_ids=[ question.id, ]) if other_questions['total'] > 0: break skip += 1 return { 'questions': [question] + other_questions['questions'], 'total': other_questions['total'] + 1 } else: question_id = args['question_id'] question = Question.get(question_id) other_questions = Question.get_filtertered_list( ontology=question.ontology, categorized='1', exclude_question_ids=[ question.id, ]) return { 'questions': [question] + other_questions['questions'], 'total': other_questions['total'] + 1 } def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('question_id', type=int, required=True) # this contains comma separated question ids parser.add_argument('similar_question_ids', type=str) args = parser.parse_args() lst = map(lambda x: x.strip(), args['similar_question_ids'].split(',')) if '' in lst: similar_question_ids = [] else: similar_question_ids = map(int, lst) question = Question.query.get(args['question_id']) question.is_similarity_marked = True question.similar_question_ids = similar_question_ids similar_questions = Question.query.filter( Question.id.in_(similar_question_ids), or_(Question.similar_question_ids == None, Question.similar_question_ids.any(question.id))).all() for q in similar_questions: if q.similar_question_ids is None: q.similar_question_ids = [question.id] else: q.similar_question_ids.append(question.id) db.session.commit() return {'error': False}
class InstituteMockTestList(AuthorizedResource): class JSObject(fields.Raw): def format(self, value): return json.loads(value) mock_test_obj = { 'id': fields.Integer, 'name': fields.String, 'description': fields.String, 'syllabus': fields.String, 'difficulty': fields.String, 'target_exam': fields.String, 'for_institutes': fields.Integer, 'is_locked': fields.Integer, 'question_ids': JSObject, 'type': fields.String, 'type_id': fields.Integer, 'prerequisite_id': fields.Integer(default=None), 'duration': fields.Integer, 'cutoff': fields.Float, 'batches_pushed_to': fields.List(fields.Nested({ 'id': fields.Integer, 'name': fields.String, 'class': fields.String })) } get_response = { 'error': fields.Boolean(default=False), 'mock_tests': fields.List(fields.Nested(mock_test_obj)), 'total': fields.Integer } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('difficulty', type=str, choices=app.config['MOCK_TEST_DIFFICULTY_LEVEL'].keys()) parser.add_argument('batches_pushed_to', type=comma_separated_ints_type) parser.add_argument('offset', type=int, default=0) parser.add_argument('limit', type=int, default=20) args = parser.parse_args() total = 0 if args['batches_pushed_to'] is not None: pushed_mock_test_ids = {} for p in PushedMockTest.query.filter(PushedMockTest.batch_id.in_(args['batches_pushed_to'])).all(): if p.mock_test_id not in pushed_mock_test_ids: pushed_mock_test_ids[p.mock_test_id] = [p.batch_id] else: pushed_mock_test_ids[p.mock_test_id].append(p.batch_id) exprs = [] exprs.append(MockTest.id.in_(pushed_mock_test_ids.keys())) if args['difficulty'] is not None: exprs.append(MockTest.difficulty == args['difficulty']) mock_tests = MockTest.query.filter(*exprs).offset(args['offset']).limit(args['limit']) total = MockTest.query.filter(*exprs).count() batches = {b.id: b for b in Batch.get_filtered(include_ids=args['batches_pushed_to'])} else: exprs = [] exprs.append(MockTest.for_institutes == True) exprs.append(MockTest.is_locked == True) if args['difficulty'] is not None: exprs.append(MockTest.difficulty == args['difficulty']) mock_tests = MockTest.query.filter(*exprs).offset(args['offset']).limit(args['limit']) batches = {b.id: b for b in Batch.get_filtered(institute_id=kwargs['user'].id)} total = MockTest.query.filter(*exprs).count() pushed_mock_test_ids = {} for p in PushedMockTest.query.filter(PushedMockTest.mock_test_id.in_([m.id for m in mock_tests]), PushedMockTest.batch_id.in_(batches.keys())).all(): if p.mock_test_id not in pushed_mock_test_ids: pushed_mock_test_ids[p.mock_test_id] = [p.batch_id] else: pushed_mock_test_ids[p.mock_test_id].append(p.batch_id) res = [] for mock_test in mock_tests: mock_test.batches_pushed_to = [{'id': b_id, 'name': batches[b_id].name, 'class': batches[b_id].clazz} for b_id in pushed_mock_test_ids.get(mock_test.id, [])] res.append(mock_test) return {'mock_tests': res, 'total': total}
class InstituteList(AuthorizedResource): institute_obj = { 'id': fields.Integer, 'name': fields.String, 'email': fields.String, 'username': fields.String, 'location': fields.String, 'mobile_no': fields.String, 'logo_url': fields.String, 'joined_at': fields.DateTime, 'last_activity': fields.DateTime, 'type': fields.Integer } get_response = { 'error': fields.Boolean(default=False), 'institutes': fields.List(fields.Nested(institute_obj)), 'total': fields.Integer } post_response = { 'error': fields.Boolean(default=False), 'institute': fields.Nested(institute_obj) } @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('page', type=int, default=1) parser.add_argument('limit', type=int, default=app.config['INSTITUTE_LIST_LIMIT']) args = parser.parse_args() institutes, total = Institute.get_list(args['page'], args['limit']) return {'institutes': institutes, 'total': total} @marshal_with(post_response) def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('email', type=str, required=True) parser.add_argument('password', type=str, required=True) parser.add_argument('location', type=str, required=True) parser.add_argument('username', type=str, required=True) parser.add_argument('mobile_no', type=str, required=True) parser.add_argument('logo', type=str) args = parser.parse_args() if args['logo'] is not None: s3 = S3() mimetype, image_data = parse_base64_string(args['logo']) mimetype_parts = mimetype.split('/') if len(mimetype_parts) > 1 and mimetype_parts[-1] in app.config[ 'ACCEPTED_IMAGE_EXTENSIONS']: # if mimetype has an extension and the extension is in the accepted list then proceed with the upload content_type = mimetype_parts[-1] url = s3.upload(image_data, content_type) else: raise UnAcceptableFileType else: url = None institute = Institute.create(name=args['name'], email=args['email'], password=md5( args['password']).hexdigest(), username=args['username'], location=args['location'], mobile_no=args['mobile_no'], logo_url=url) return {'institute': institute}
for value in display_info.notes: response.append({ "type": 'notes', # Note: type should be 'note' but for retrocompatibility, we can't change it "rel": 'notes', "id": value.uri, 'value': value.note, 'internal': True }) return response instance_status = { "data_version": fields.Integer(), "end_production_date": fields.String(), "is_connected_to_rabbitmq": fields.Boolean(), "last_load_at": fields.String(), "last_rt_data_loaded": fields.String(), "last_load_status": fields.Boolean(), "kraken_version": fields.String(attribute="navitia_version"), "nb_threads": fields.Integer(), "publication_date": fields.String(), "start_production_date": fields.String(), "status": fields.String(), "is_open_data": fields.Boolean(), "is_realtime_loaded": fields.Boolean(), "realtime_proxies": fields.Raw(), } instance_parameters = { 'scenario': fields.Raw(attribute='_scenario_name'),
class MockTestList(AuthorizedResource): class Qids(fields.Raw): def format(self, value): return json.loads(value) mock_test_obj = { 'id': fields.Integer, 'name': fields.String, 'description': fields.String, 'syllabus': fields.String, 'difficulty': fields.Integer, 'target_exam': fields.Integer, 'for_institutes': fields.Integer, 'is_locked': fields.Integer, 'question_ids': Qids, 'type': fields.String, 'type_id': fields.Integer, 'prerequisite_id': fields.Integer(default=None), 'duration': fields.Integer, 'cutoff': fields.Float } get_response = { 'error': fields.Boolean(default=False), 'mock_tests': fields.List(fields.Nested(mock_test_obj)), 'total': fields.Integer } post_response = { 'error': fields.Boolean(default=False), 'mock_test': fields.Nested(mock_test_obj) } @classmethod def date_json_type(cls, data): """ Parse the string date and output the datetime.date object. """ try: print data date = datetime.datetime.strptime(data, "%Y-%m-%d").date() return date except Exception as e: raise ValueError("Date is not given in the proper format.") @classmethod def question_ids_json_type(cls, data): """ Parse the question ids json Questions are supplied in the format { <parent_id1>: { "order": 2, "q_ids": [q_id1, q_id2] }, <parent_id2>: { "order": 1, "q_ids": [q_id4, q_id5] } } :param data: :return: """ try: parsed_data = json.loads(data) if not isinstance(parsed_data, dict): raise ValueError('question_ids should be in the form of object') for subject_id, d in parsed_data.items(): if 'order' not in d or not isinstance(d['order'], int): raise ValueError('order should be present for subject and should be integer') if 'q_ids' not in d: raise ValueError('q_ids should be present for subject and should be a non empty array') return data except Exception as e: raise ValueError("question_ids should be json") @marshal_with(get_response) def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('difficulty', type=str, choices=app.config['MOCK_TEST_DIFFICULTY_LEVEL'].keys()) parser.add_argument('target_exam', type=str, choices=app.config['TARGET_EXAMS'].keys()) parser.add_argument('is_locked', type=int, choices=[0,1]) parser.add_argument('for_institutes', type=int, choices=[0,1]) parser.add_argument('page', type=int, default=1) parser.add_argument('limit', type=int, default=app.config['MOCK_TEST_LIST_LIMIT']) args = parser.parse_args() exprs = [] if args['difficulty'] is not None: exprs.append(MockTest.difficulty == args['difficulty']) if args['target_exam'] is not None: exprs.append(MockTest.target_exam == args['target_exam']) if args['is_locked'] is not None: exprs.append(MockTest.is_locked == (args['is_locked'] == 1)) if args['for_institutes'] is not None: exprs.append(MockTest.for_institutes == (args['for_institutes'] == 1)) mock_test_pag_obj = MockTest.query.filter(*exprs).order_by(MockTest.created_at.desc()).paginate(args['page'], args['limit']) mock_tests = mock_test_pag_obj.items total = mock_test_pag_obj.total return {'mock_tests': mock_tests, 'total': total} @marshal_with(post_response) def post(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True) parser.add_argument('difficulty', type=str, required=True, choices=app.config['MOCK_TEST_DIFFICULTY_LEVEL'].keys()) parser.add_argument('description', type=unicode) parser.add_argument('syllabus', type=unicode) parser.add_argument('target_exam', type=str, required=True, choices=app.config['TARGET_EXAMS'].keys()) parser.add_argument('for_institutes', type=int, required=True, choices=[0, 1]) parser.add_argument('type', type=str, required=True, choices=app.config['MOCK_TEST_TYPES'].keys()) parser.add_argument('type_id', type=int) parser.add_argument('prerequisite_id', type=int) parser.add_argument('duration', type=int, required=True) parser.add_argument('cutoff', type=float, required=True) parser.add_argument('date_closed', type=bool, required=True) parser.add_argument('opening_date', type=self.__class__.date_json_type) # comma separated question ids parser.add_argument('question_ids', type=self.__class__.question_ids_json_type) args = parser.parse_args() for k,v in args.items(): print "{0}: {1}".format(k, v) params = { "name": args['name'], "difficulty": args['difficulty'], "description": args['description'], "syllabus": args['syllabus'], "target_exam": args['target_exam'], "for_institutes": args['for_institutes']==1, "question_ids": args['question_ids'], "type": args['type'], "type_id": args['type_id'], "prerequisite_id": args['prerequisite_id'], "duration": args['duration'], "cutoff": args['cutoff'], "created_by_type": kwargs['user_type'].id, "created_by_id": kwargs['user'].id, "date_closed": args['date_closed'], "opening_date": args.get('opening_date') } mock_test = MockTest.create(**params) return {'mock_test': mock_test}