class MyLiveView(ModelView): column_list = ('speaker', 'title', 'live_description', 'seats_count', 'price') column_labels = dict(speaker='作者', title='标题', live_description='描述', seats_count='售出', price='价格') column_sortable_list = ('speaker', 'seats_count', 'price') column_editable_list = ['title'] can_create = False inline_models = (LiveContent, ) def _format_price(view, context, model, name): price = int(model['price']) / 100 return Markup("¥{}".format(price)) column_formatters = {'price': _format_price} column_extra_row_actions = [ EndpointLinkRowAction( 'glyphicon glyphicon-download', 'tools.crawl', ), EndpointLinkRowAction( 'glyphicon glyphicon-transfer', 'tools.transform_live', ) ]
class WatcherView(AuthModelView): can_view_details = True column_list = ('game', 'info', 'config') column_details_list = ('game', 'info', 'config', 'events') form_excluded_columns = ['events'] inline_models = [WatcherConfig] form_args = { 'threadClass': { 'label': 'Watcher Type', 'choices': [('lamon.watcher.plugin.source_engine.SourceEngineWatcher', 'Source Engine Watcher'), ('lamon.watcher.plugin.quake3.Quake3Watcher', 'Quake3 Watcher'), ('lamon.watcher.plugin.minecraft.MinecraftWatcher', 'Minecraft Watcher'), ('tests.watcher.ValueWatcher', 'Fake Value Watcher')] } } form_overrides = {'threadClass': SelectField, 'config': HiddenField} column_extra_row_actions = [ EndpointLinkRowAction('glyphicon glyphicon-play', 'watchers.start'), EndpointLinkRowAction('glyphicon glyphicon-stop', 'watchers.stop'), EndpointLinkRowAction('glyphicon glyphicon-refresh', 'watchers.restart') ]
class UserAdmin(BaseAdminView): # def is_visible(self): # return False column_list = ['id', 'full_name', 'email'] column_searchable_list = ('id', "full_name", 'email') column_filters = ("id", "full_name", "email") form_create_rules = ('email', "is_active") form_edit_rules = ('email', "is_active") column_extra_row_actions = [ EndpointLinkRowAction('glyphicon glyphicon-user', 'user.action_play', title="Login as User"), ] @expose('impersonate/<id>', methods=('Get', )) def action_play(self, *args, **kwargs): user = User.query.get(kwargs['id']) login_user(user) if user.corporate != None: corporate_id = user.corporate.id CookieHelper.set_corporate_cookie(corporate_id) return self.handle_action()
class UserModelView(BaseModelView): can_delete = False # disable model deletion can_create = False can_view_details = True can_export = True column_searchable_list = ["email"] form_excluded_columns = [ "password", "subscriptions", "export_requests", "created_at", "bulk_search_requests", "api_keys", "features", ] column_exclude_list = [ "password", "first_name", "last_name", ] column_details_list = [ "id", "plan_slug", "feature_slugs", "created_at", "first_name", "last_name", "is_active", "is_admin", ] column_export_exclude_list = [ "password", ] column_default_sort = ("created_at", True) column_list = [ "email", "plan_slug", "created_at", "is_active", "is_admin", ] column_extra_row_actions = [ EndpointLinkRowAction( "fa fa-sign-in-alt", "admin.user.login_as", id_arg="user_id", ) ] @expose("/login-as/<user_id>") def login_as(self, user_id): from .models.accounts import User user = User.query.filter_by(id=user_id).first_or_404() login_user(user, remember=False) identity_changed.send( current_app._get_current_object(), identity=Identity(user.id) ) flash(f"You are logged in as {user.email}.", "success") redirect_url = url_for("public.home") return redirect(redirect_url)
class StorageView(AuthModelView): """ 存储管理模块 """ can_create = True can_edit = True can_delete = False can_view_details = True details_modal = True column_exclude_list = ["id", "uid", "path"] form_excluded_columns = [ "saved", "uid", "path", "created", "modified", "deleted", "filetype", ] column_filters = ["created", "modified", "storetype", "filetype"] form_extra_fields = {"file": JustUploadField("文件")} column_extra_row_actions = [ EndpointLinkRowAction( icon_class="fas fa-download", endpoint="admin.views.storages.storage_file", id_arg="file_id", ) ] @expose("file/<int:file_id>", methods=["GET"]) def storage_file(self, file_id): """访问文件""" storage = self.model.get_by_id(file_id) return send_file( storage.store.stream, attachment_filename=storage.name, mimetype=storage.store.content_type, as_attachment=False, ) def on_model_change(self, form, model, is_created): """保存文件处理""" if "file" in form: model.store = form["file"].data if is_created: model.save() elif model.deleted is True: model.delete() else: # TODO 当发生更新时检查文件是否发生改变 model.update() super().on_model_change(form, model, is_created)
class UserAdmin(BaseUserAdmin): list_template = 'canella/admin/user/list.html' can_create = False column_exclude_list = ['password', 'slug', 'profile'] form_excluded_columns = [ 'password', 'posts', 'profile', 'confirmed_at', 'slug' ] column_extra_row_actions = [ EndpointLinkRowAction(icon_class="fa fa-lock", endpoint='.change_password', title=lazy_gettext("Change Password"), id_arg='pk'), ] @expose('/<int:pk>/change-password/', methods=['GET', 'POST']) def change_password(self, pk): user = self.get_one(str(pk)) form = CanellaChangePasswordForm(user=user) if form.validate_on_submit(): change_password(user, form.password.data) db.session.commit() if user.email == current_user.email: logout_user() flash(gettext('Password changed successfully')) return redirect(url_for('.index_view')) return self.render('admin/model/create.html', form=form) @expose('/<int:pk>/deactivate/', methods=['GET', 'POST']) def deactivate_user(self, pk): if user.is_active: user = self.get_one(str(pk)) user.is_active = False db.session.commit() flash(gettext('Account deactivated successfully')) return redirect(url_for('.index_view')) @expose('/<int:pk>/activate/', methods=['GET', 'POST']) def activate_user(self, pk): user = self.get_one(str(pk)) if not user.is_active: user.is_active = True db.session.commit() flash(gettext('Account activated successfully')) return redirect(url_for('.index_view')) @expose('/register/', methods=['GET', 'POST']) def register(self): form = CanellaRegisterForm() if form.validate_on_submit(): should_confirm = form.send_confirmation.data del form.send_confirmation register_user(should_confirm=should_confirm, **form.to_dict()) return redirect(url_for('.index_view')) return self.render('admin/model/create.html', form=form)
class TranscriptAdminModelView(AdminModelView): column_searchable_list = ['id', 'student_name', 'user_id', 'user.email'] inline_models = [Year] inline_model_form_converter = TranscriptInlineModelConverter column_extra_row_actions = [ EndpointLinkRowAction("glyphicon icon-print", 'transcript.print'), EndpointLinkRowAction("glyphicon icon-cog", 'transcriptsettings.edit_view') ] def __init__(self, db, *args, **kwargs): super().__init__(Transcript, db._session, *args, **kwargs) self.transcript_service = TranscriptService(db) @expose('/print/<int:id>') def print(self, id): transcript = self.transcript_service.get(id) if transcript is None: return abort(404) transcript_grader = GradingService.get_transcript_grader( transcript.grading_scale, transcript.ap_grading_scale) return render_pdf(transcript, transcript_grader)
class FormAdmin(PageAdmin): inline_models = [(Field, dict( form_columns=['id', 'name', 'label', 'description', 'type', 'choices', 'default', 'required', 'max_length'], form_extra_fields={'type': SelectField(label=Field.type.info['label'], description=Field.type.info['description'], choices=sorted(Field.type.info['choices']))} ),),] column_extra_row_actions = list(PageAdmin.column_extra_row_actions) column_extra_row_actions.append(EndpointLinkRowAction(icon_class='fa fa-download', endpoint='.export_entries', title=lazy_gettext('Export Entries as CSV'), id_arg='pk')) form_excluded_columns = ["children", "contenttype", "slug_path"] form_rules = list(PageAdmin.form_rules) form_rules.insert(6, 'fields') form_rules.insert(7, 'submit_text') form_rules.insert(8, 'submit_message') form_overrides = dict(PageAdmin.form_overrides) form_overrides.update({ 'submit_message': RichTextAreaField, }) @expose('/export-entries/<int:pk>') def export_entries(self, pk): """Taken from Flask-Admin with some modifications, no shame!""" form = self.get_one(str(pk)) filename = "attachment; filename=%s.csv" %("%s-%s" %(form.slug, date_stamp(form.updated))) class Echo(object): """ An object that implements just the write method of the file-like interface. """ def write(self, value): """ Write the value by returning it, instead of storing in a buffer. """ return value writer = csv.writer(Echo()) def generate(): # Append the column titles at the beginning titles = [csv_encode('date')] + [csv_encode(field.name) for field in form.fields] yield writer.writerow(titles) for entry in form.entries: vals = [csv_encode(entry.created.isoformat())] + [csv_encode(field.value) for field in entry.fields] yield writer.writerow(vals) return Response( stream_with_context(generate()), headers={'Content-Disposition': filename}, mimetype='text/csv' )
class TestBedView(MyObjectView): column_list = [ 'name', 'owner', 'rigs', ] form_excluded_columns = ['connect_chart', ] column_extra_row_actions = [ LinkRowAction('icon-eye-open', './{row_id}'), EndpointLinkRowAction('', 'testbed.index_view') ] @expose('/<testbed_id>') def show_chart(self, testbed_id): tb = Testbed.query.filter_by(id=testbed_id).first() rigs = tb.rigs rig_names = [rig.name for rig in rigs] hosts = tb.hosts host_names = [host.name for host in hosts] rig_names.extend(host_names) if tb.connect_chart is None: relation_sample = [] else: relation_sample = json.loads(tb.connect_chart) rig_connects = RigConnection.query.all() rig_connect_names = [rig_connect.name for rig_connect in rig_connects] host_usages = HostUsage.query.all() host_usage_names = [host_usage.name for host_usage in host_usages] rig_connect_names.extend(host_usage_names) return self.render('testbed2.html', rig_names=rig_names, tb_name=tb.name, rig_connect_names=rig_connect_names, relation=relation_sample) @expose('/save/<tb_name>', methods=['GET', 'POST']) def save(self, tb_name): print(tb_name) content = request.form.get('content') print(content) # print(Testbed.query.filter_by(name=tb_name).first()) tb = Testbed.query.filter_by(name=tb_name).first() tb.connect_chart = content tb.save() return 'saved'
class UserModelView(BaseModelView): column_list = ('id', 'name', 'username') column_default_sort = 'id' can_delete = False column_extra_row_actions = [ EndpointLinkRowAction('glyphicon glyphicon-envelope', '.chat') ] @expose('/chat', methods=['GET', 'POST']) def chat(self): id = request.args.get('id') recipient = User.query.get(id) if recipient is None: flash('user_id is error.', 'error') return redirect(url_for('.index_view')) form = ChatInputForm() if request.method == 'POST' and form.validate(): msg = Message(sender=current_user, recipient=recipient, body=form.message.data) db.session.add(msg) db.session.commit() # flash('发送消息成功') messages = Message.query.filter( or_( and_( Message.sender == current_user, Message.recipient == recipient ), and_( Message.sender == recipient, Message.recipient == current_user ), ) ).all() return self.render('/chat.html', sender=current_user, recipient=recipient, form=form, messages=messages)
class LiveContentView(ModelView): column_list = ('sender', 'content', 'likes', 'type', 'created_at', 'image_or_audio') column_labels = dict(sender='作者', content='内容', likes='顶', type='类型', created_at='时间', image_or_audio='语音播放') column_sortable_list = ('sender', 'likes', 'type', 'created_at') column_editable_list = ['content'] column_searchable_list = ('content', ) column_filters = (ReferenceObjectIdFilter( column=LiveContent.live_title, name='live_title', options=_get_live_title_option()), 'type') def _list_thumbnail(view, context, model, name): if model['type'] == 'image': imgurl = str(model['id']) + '.png' return Markup("<a href='%s' target='_blank'>查看图片</a>" % url_for('static', filename=imgurl)) elif model['type'] == 'audio': return Markup('<audio controls height="100" width="100">' '<source src="%s" type="audio/aac" />' '</audio>' % model['url']) else: return '' column_formatters = {'image_or_audio': _list_thumbnail} can_edit = True edit_modal = True can_export = True export_types = ['xls'] column_extra_row_actions = [ EndpointLinkRowAction( 'glyphicon glyphicon-transfer', 'tools.transform', ) ]
class ResultModelView(AuthRequiredView): column_extra_row_actions = [ EndpointLinkRowAction('glyphicon icon-eye-open', 'studentresults.index') ] column_list = ["user", "grade", "n_correct", "n_total", "datetime"] column_labels = { "n_correct": "Правильных ответов", "n_total": "Всего вопросов", "grade": "Оценка", "datetime": "Время окончания", "de_0": "Освоение ДЕ №1", "de_1": "Освоение ДЕ №2", "de_2": "Освоение ДЕ №3", "de_3": "Освоение ДЕ №4", "de_4": "Освоение ДЕ №5", "de_5": "Освоение ДЕ №6", "user": "******", "user.name": "Пользователь / ФИО", "user.group": "Пользователь / Группа", "user.login": "******", "user.attempts": "Пользователь / Число попыток", } column_formatters = { "datetime": lambda v, c, m, p: m.datetime.strftime("%H:%M:%S %d.%m.%Y"), "user": lambda v, c, m, p: f"{m.user.name} ({m.user.group})", "grade": lambda v, c, m, p: "отл." if m.n_correct / m.n_total >= app.config["GRADE_RATIOS"][2] else "хор." if m.n_correct / m.n_total >= app.config["GRADE_RATIOS"][1] else "удов." if m.n_correct / m.n_total >= app.config["GRADE_RATIOS"][0] else "неуд." } column_filters = ["user.name", "user.login", "user.group", "user.attempts", "n_correct", "n_total", "datetime"] column_exclude_list = ["variant"] form_excluded_columns = ["variant"] column_sortable_list = [("user", "user.name"), "n_correct", "n_total", "datetime"] column_default_sort = ("datetime", True) def is_editable(self, name): return False
class RigView(MyObjectView): inline_models = [(RigInfo, inline_form_options), ] column_exclude_list = ['io_interfaces', 'iscsi_interfaces', 'replication_async_interfaces', 'replication_sync_interfaces', 'state', 'status'] column_editable_list = ['model', 'owner', 'device'] inline_models = [(RigInfo, inline_form_options), ] column_extra_row_actions = [ LinkRowAction('icon-eye-open', './{row_id}'), EndpointLinkRowAction('', 'rig.index_view') ] @expose('/<rig_id>') def show_chart(self, rig_id): rig = Rig.query.filter_by(id=rig_id).first() tbs = Testbed.query.all() rig_map_tb = [] for item in tbs: print(f'tb_name :{item.name}') rigs = item.rigs for checked_rig in rigs: if rig.name == checked_rig.name: rig_map_tb.append([rig.name, item.name, 'Used']) return self.render('rig.html', relation=rig_map_tb)
class UserView(CVAdminModelView): can_create = True can_edit = True can_delete = True # inline_models = [(Role, dict(form_columns=['id', 'name']))] column_list = ('id', 'username', 'password', 'email', 'roles', 'active', 'create_at', 'update_at', 'remark') column_labels = dict(id='用户ID', username='******', password='******', email='邮箱地址', roles='角色', active='启用', create_at='创建时间', update_at='更新时间', remark='备注') column_filters = ('roles.name', ) column_formatters = dict( password=lambda v, c, m, p: '••••••', active=lambda v, c, m, p: get_yesno_display(m.active), create_at=lambda v, c, m, p: display_datetime(m.create_at), update_at=lambda v, c, m, p: display_datetime(m.update_at)) # def get_action_url(self): # self.get_url('.edit_view', id = self.get_pk_value(self.row), # url = get_redirect_target() or self.get_url('.index_view')) column_extra_row_actions = [ # LinkRowAction('fa fa-key','/admin/user/edit/?id={row_id}&url=%2Fadmin%2Fuser%2F'), EndpointLinkRowAction('fa fa-key', 'user.resetpass_view', title='重置密码') ] form_args = dict(roles=dict(validators=[DataRequired()])) form_create_rules = ( rules.FieldSet(('username', 'email', 'remark'), '基本信息'), # rules.FieldSet(('roles', 'apikey', 'active'), 'Permission'), rules.FieldSet(('roles', 'active'), '权限设置'), # rules.FieldSet(('password', 'password_confirm'), '账号安全') ) form_edit_rules = ( rules.FieldSet(('username', 'email', 'remark'), '基本信息'), rules.FieldSet(('roles', 'active'), '权限设置'), # rules.Header('重置密码'), # rules.FieldSet(('new_password', 'new_password_confirm'), '重置密码') # rules.Field() ) def __init__(self, model, session): CVAdminModelView.__init__(self, model, session, '用户', '系统设置') def is_accessible(self): from common.login import admin_permission if request.endpoint == 'user.resetpass_view': if (login.current_user.id == int( request.values.get('id'))) or admin_permission.can(): return login.current_user.is_authenticated else: return False else: if admin_permission.can(): return login.current_user.is_authenticated else: return False def get_create_form(self): form = self.scaffold_form() form.username = fields.StringField( '用户名', [validators.required(message='用户名是必填字段')]) # form.password = fields.PasswordField('密码', [validators.required(message = '密码是必填字段')]) # form.password_confirm = fields.PasswordField('密码确认', # [validators.required(message = '密码是必填字段'), # validators.equal_to(fieldname = 'password', # message = '确认密码须一致')]) form.active = fields.BooleanField( '启用状态', [validators.required(message='启用状态是必填字段')], default=True) return form def get_edit_form(self): form = self.scaffold_form() delattr(form, 'password') # form.new_password = fields.PasswordField('新密码') # form.new_password_confirm = fields.PasswordField('密码确认', # [validators.equal_to(fieldname = 'new_password', # message = '确认密码须一致')]) form.active = fields.BooleanField( '启用状态', [validators.required(message='启用状态是必填字段')], default=True) return form def on_model_change(self, form, model, is_created): if not is_created: if hasattr(form, 'new_password'): model.password = generate_password_hash(form.new_password.data) else: model.password = generate_password_hash(model.password) def get_action_form(self): ''' 定制Action :return: ''' class ResetpassForm(self.form_base_class): form_widget_args = {} form_edit_rules = [ rules.Field('new_password'), rules.Field('new_password_confirm') ] _form_edit_rules = rules.RuleSet(self, form_edit_rules) action = HiddenField('') url = HiddenField('') new_password = fields.PasswordField( '新密码', [validators.required(message='密码是必填字段')]) new_password_confirm = fields.PasswordField( '密码确认', [ validators.equal_to(fieldname='new_password', message='确认密码须一致') ]) return ResetpassForm @expose('/resetpass/', methods=('GET', 'POST')) def resetpass_view(self): """ Reset password view """ return_url = get_redirect_target() or self.get_url('.index_view') if not self.can_edit: return redirect(return_url) id = get_mdict_item_or_list(request.args, 'id') if id is None: return redirect(return_url) model = self.get_one(id) if model is None: flash(gettext('Record does not exist.'), 'error') return redirect(return_url) form = self.action_form(obj=model) if not hasattr(form, '_validated_ruleset') or not form._validated_ruleset: self._validate_form_instance(ruleset=form._form_edit_rules, form=form) if self.validate_form(form): if self.update_model(form, model): flash(gettext('Record was successfully saved.'), 'success') if '_add_another' in request.form: return redirect( self.get_url('.create_view', url=return_url)) elif '_continue_editing' in request.form: return redirect(request.url) else: # save button return redirect( self.get_save_return_url(model, is_created=False)) if request.method == 'GET' or form.errors: self.on_form_prefill(form, id) form_opts = FormOpts(widget_args=form.form_widget_args, form_rules=form._form_edit_rules) template = 'model/resetpass.html' return self.render(template, model=model, form=form, form_opts=form_opts, return_url=return_url)
class ExternalObjectView(DefaultView): def __init__(self, *args, **kwargs): kwargs['category'] = 'External Objects' kwargs['endpoint'] = kwargs['name'].lower() + 'object' super(ExternalObjectView, self).__init__(ExternalObject, *args, **kwargs) can_view_details = True can_export = True # TODO: Export formatters export_types = ['csv', 'xls'] column_details_list = ('id', 'type', 'attributes_list', 'links_list') column_formatters = { 'name': attribute_formatter(partial(eq, ValueType.NAME)), 'title': attribute_formatter(partial(eq, ValueType.TITLE)), 'date': attribute_formatter(partial(eq, ValueType.DATE), filter=lambda t: len(t) == 4), 'genres': attribute_formatter(partial(eq, ValueType.GENRES), limit=3), 'country': attribute_formatter(partial(eq, ValueType.COUNTRY), filter=lambda t: len(t) == 2), 'duration': attribute_formatter(partial(eq, ValueType.DURATION), filter=lambda t: t.replace('.', '').isdigit(), limit=1), 'attributes': attribute_formatter(show_score=True), 'attributes_list': macro('attributes_list'), 'links_list': macro('links_list'), 'links': count_formatter } column_extra_row_actions = [ EndpointLinkRowAction('glyphicon icon-search', 'allobject.index_view', id_arg='flt0_0') ] inline_models = ((Value, dict(form_columns=('id', 'type', 'text'))), (ObjectLink, dict(form_columns=('id', 'platform', 'external_id')))) column_filters = [ ExternalObjectSimilarFilter(name='Similar'), ExternalObjectPlatformFilter( column=Platform.country, name='Platform', options=[(c[0], str(c[0]).upper()) for c in db.session.query(Platform.country).distinct()]), ExternalObjectPlatformFilter(column=Platform.type, name='Platform', options=[(t.name, t.name) for t in PlatformType]), ExternalObjectPlatformFilter( column=Platform.slug, name='Platform', options=[(p.slug, p.name) for p in db.session.query(Platform.slug, Platform.name)]), ExternalObjectPlatformFilter( column=Platform.slug, invert=True, name='Platform', options=[(p.slug, p.name) for p in db.session.query(Platform.slug, Platform.name)]), ] def get_query(self): q = super(ExternalObjectView, self).get_query() if hasattr(self, 'external_object_type'): q = q.filter(ExternalObject.type == self.external_object_type) return q def get_count_query(self): q = super(ExternalObjectView, self).get_count_query() if hasattr(self, 'external_object_type'): q = q.filter(ExternalObject.type == self.external_object_type) return q
class PendingApprovedModelView(ModelView): edit_modal = True column_editable_list = ('task', 'calculated_time', 'kind', 'approved') column_searchable_list = ('id', 'number', 'task', 'date') column_sortable_list = ('task', 'calculated_time') column_labels = dict(id=u'主键', name=u'工作者', number=u'工号', date=u'日期', airplane=u'飞机', task=u'项目', standard_time=u'标准工时', worker_number=u'标准人数', calculated_time=u'计算工时', completed=u'完成情况', role=u'角色', note=u'说明', belongto_team=u'班组', kind=u'工作类别', approved=u'是否审核') column_extra_row_actions = [ EndpointLinkRowAction( 'off glyphicon glyphicon-check', 'timesheet.approve_view', ) ] # def get_query(self): # return self.session.query( # self.model).filter(self.model.approved == u'否') # def get_count_query(self): # return self.session.query( # func.count('*')).filter(Timesheet.approved == u'否') def get_filters(self): _dynamic_filters = getattr(self, 'dynamic_filters', None) if _dynamic_filters: return (super(PendingApprovedModelView, self).get_filters() or []) + _dynamic_filters else: return super(PendingApprovedModelView, self).get_filters() @expose('/') def index_view(self): self.dynamic_filters = [] self.dynamic_filters.extend([ FilterEqual(column=Timesheet.belongto_team, name=u'班组', options=get_all_team_names), # Add further dynamic filters here ]) self._refresh_filters_cache() return super(PendingApprovedModelView, self).index_view() @expose('/approve/', methods=('GET', )) def approve_view(self): """ Approve user model view. Only GET method is allowed. """ return_url = get_redirect_target() or self.get_url( 'timesheet.details_view') id = request.args["id"] model = self.get_one(id) if model is None: flash(u'用户不存在', u'error') return redirect(return_url) if model.approved == u'是': flash(u'已经审核, 无需重复审核.', u'warning') return redirect(return_url) model.approved = u'是' self.session.add(model) self.session.commit() flash(u'已审核', u'success') return redirect(return_url) @action('approve', u'审核', u'你确定要将所选择的项目设置为已审核?') def action_approve(self, ids): redirect_response = redirect(url_for('timesheet.index_view')) try: query = Timesheet.query.filter(Timesheet.id.in_(ids)) count = 0 for timesheet in query.all(): if timesheet.approved == u'是': pass else: timesheet.approved = u'是' count += 1 db.session.commit() flash(u'审核 {} 个工时成功.'.format(count), 'success') return redirect_response except Exception as e: if not self.handle_view_exception(e): raise flash(u'审核失败:{}'.format(str(e)), 'error')
class ExternalObjectView(DefaultView): def __init__(self, *args, **kwargs): kwargs["category"] = "External Objects" kwargs["endpoint"] = kwargs["name"].lower().replace(" ", "") super(ExternalObjectView, self).__init__(ExternalObject, *args, **kwargs) can_view_details = True can_export = True # TODO: Export formatters export_types = ["csv", "xls"] column_details_list = ("id", "type", "values_list", "links_list") column_formatters = { "name": attribute_formatter(partial(eq, ValueType.NAME)), "title": attribute_formatter(partial(eq, ValueType.TITLE)), "date": attribute_formatter(partial(eq, ValueType.DATE), filter=lambda t: len(t) == 4), "genres": attribute_formatter(partial(eq, ValueType.GENRES), limit=3), "country": attribute_formatter(partial(eq, ValueType.COUNTRY), filter=lambda t: len(t) == 2), "duration": attribute_formatter( partial(eq, ValueType.DURATION), filter=lambda t: t.replace(".", "").isdigit(), limit=1, ), "series": series_formatter, "season": meta_formatter("season"), "episode": meta_formatter("episode"), "episode_details": macro("episode_details"), "episodes": episodes_formatter, "episodes_list": macro("episodes_list"), "values": attribute_formatter(show_score=True), "values_list": macro("values_list"), "links_list": macro("links_list"), "links": count_formatter, } column_extra_row_actions = [ EndpointLinkRowAction("glyphicon icon-search", "allobjects.index_view", id_arg="flt0_0") ] inline_models = ( (Value, dict(form_columns=("id", "type", "text"))), (ObjectLink, dict(form_columns=("id", "platform", "external_id"))), ) column_filters = [ ExternalObjectSimilarFilter(name="Similar"), ExternalObjectPlatformFilter( column=Platform.country, name="Platform", options=[(c[0], str(c[0]).upper()) for c in db.session.query(Platform.country).distinct()], ), ExternalObjectPlatformFilter( column=Platform.type, name="Platform", options=[(t.name, t.name) for t in PlatformType], ), ExternalObjectPlatformFilter( column=Platform.slug, name="Platform", options=[(p.slug, p.name) for p in db.session.query(Platform.slug, Platform.name)], ), ExternalObjectPlatformFilter( column=Platform.slug, invert=True, name="Platform", options=[(p.slug, p.name) for p in db.session.query(Platform.slug, Platform.name)], ), ] def get_query(self): q = (super(ExternalObjectView, self).get_query().options( joinedload(ExternalObject.values).joinedload(Value.sources))) if hasattr(self, "external_object_type"): q = q.filter(ExternalObject.type == self.external_object_type) return q def get_count_query(self): q = super(ExternalObjectView, self).get_count_query() if hasattr(self, "external_object_type"): q = q.filter(ExternalObject.type == self.external_object_type) return q
class APIKeyView(CVAdminModelView): can_create = True can_edit = False can_delete = True column_labels = dict(id='ID', botid='机器人', key='API Key', secret='API Secret', create_at='创建时间', update_at='更新时间') column_formatters = dict( botid=lambda v, c, m, p: get_botname(m.botid), create_at=lambda v, c, m, p: display_datetime(m.create_at), update_at=lambda v, c, m, p: display_datetime(m.update_at)) column_extra_row_actions = [ EndpointLinkRowAction('fa fa-refresh', 'apikey.refresh_view', title='更新Key和Secret') ] form_create_rules = ('botid', ) form_edit_rules = ('botid', 'new_key', 'new_secret') def __init__(self, model, session): CVAdminModelView.__init__(self, model, session, 'API密钥', '系统设置') def is_accessible(self): from common.login import admin_permission if admin_permission.can(): return login.current_user.is_authenticated else: return False def get_create_form(self): form = self.scaffold_form() def query_factory(): return [r.id for r in Bot.findall()] def get_pk(obj): return obj def get_label(obj): return Bot.find(obj).name from wtforms.ext.sqlalchemy.fields import QuerySelectField form.botid = QuerySelectField( '机器人', [validators.required(message='机器人是必填字段')], query_factory=query_factory, get_label=get_label, get_pk=get_pk, widget=Select2Widget()) return form def get_edit_form(self): form = self.scaffold_form() delattr(form, 'key') delattr(form, 'secret') form.botid = StringField('机器人', render_kw={'readonly': True}) form.new_key = StringField('新API Key', render_kw={'readonly': True}) form.new_secret = StringField('新API Secret', render_kw={'readonly': True}) return form def on_form_prefill(self, form, id): form.new_key.data = generate_key(32, True, False, True) form.new_secret.data = generate_key(12, False, True, True) def on_model_change(self, form, model, is_created): if not is_created: if form.new_key.data: model.key = form.new_key.data model.secret = form.new_secret.data @expose('/refresh/', methods=('GET', 'POST')) def refresh_view(self): """ Refresh key and secret """ return_url = get_redirect_target() or self.get_url('.index_view') id = get_mdict_item_or_list(request.args, 'id') if id is not None: self.get_one(id).refresh() return redirect(return_url)
class Tes(BaseModelView): can_create = False can_edit = True can_delete = False page_size = 10 column_list = ['station_id', 'country', 'state', 'series', 'lat', 'lon'] column_default_sort = ('station_id', True) column_sortable_list = ['station_id'] column_labels = dict(station_id='Station Name', country='Country', state='State', series='Series', lat='Latitude', lon='Longitude') # Rename 'title' column in list view column_searchable_list = ['station_id'] can_export = True export_max_rows = 1000 export_types = ['csv', 'xls'] column_extra_row_actions = [ #LinkRowAction('icon-edit', 'http://direct.link/?id={row_id}'), EndpointLinkRowAction( icon_class='icon-search glyphicon glyphicon-search', endpoint='dataview.series', title="View Details", id_arg='station_name') ] def create_model(self, **kwargs): pass def delete_model(self, **kwargs): pass def get_pk_value(self, model): return model.station_id def get_list(self, page, sort_field, sort_desc, search, filters, **kwargs): station_dao, series_dao, _ = setup_daos() count = station_dao.count() stations = station_dao.get_limited(limit=self.page_size, offset=page * self.page_size) ret = list() for station in stations: ret.append( Station(station_id=station[0], country=station[6], state=station[1], series=series_dao.count(station_id=station[0]), lat=station[3], lon=station[4])) return count, ret def get_one(self, id, **kwargs): station_dao, _, _ = setup_daos() station = station_dao.get_for_name(station_name=id) return Station(station_id=station[0], country=station[6], state=station[1], series=0, lat=station[3], lon=station[4]) # def scaffold_list_columns(self): # return ['name', 'field'] # def scaffold_sortable_columns(self): # return None def scaffold_form(self): class MyForm(form.Form): station_id = StringField('Station Name') country = StringField('Country') lat = FloatField('Latitude') lon = FloatField('Longitude') return MyForm def update_model(self, form, model): print('Currently not supported') return True
class FormAdmin(PageAdmin): column_extra_row_actions = [ EndpointLinkRowAction( icon_class="fa fa-download", endpoint=".export_entries", title=lazy_gettext("Export Entries as CSV"), id_arg="pk", ), EndpointLinkRowAction( icon_class="fa fa-table", endpoint=".view_entries", title=lazy_gettext("View Entries"), id_arg="pk", ), ] form_excluded_columns = list(PageAdmin.form_excluded_columns) + [ "author", "created", "updated", "entries", ] form_columns = list(PageAdmin.form_columns) form_columns.insert(6, "fields") form_columns.insert(7, "submit_text") form_columns.insert(8, "submit_message") form_overrides = {"submit_message": CkeditorTextAreaField} inline_models = [ ( Field, dict( form_columns=[ "id", "name", "label", "description", "type", "choices", "default", "required", "max_length", ], form_extra_fields={ "type": SelectField( label=Field.type.info["label"], description=Field.type.info["description"], choices=field_type_choices, ) }, ), ) ] @expose("/export-entries/<int:pk>") def export_entries(self, pk): """Taken from Flask-Admin with some modifications, no shame!""" form = self.get_one(str(pk)) filename = "attachment; filename=%s" % _gen_csv_file_name(form) class Echo(object): """ An object that implements just the write method of the file-like interface. """ def write(self, value): """ Write the value by returning it, instead of storing in a buffer. """ return value writer = csv.writer(Echo()) def generate(): # Append the column titles at the beginning titles = [csv_encode("date")] + [ csv_encode(field.name) for field in form.fields ] yield writer.writerow(titles) for entry in form.entries: vals = [csv_encode(entry.created.isoformat())] + [ csv_encode(_process_field_value(field)) for field in entry.fields ] yield writer.writerow(vals) return Response( stream_with_context(generate()), headers={"Content-Disposition": filename}, mimetype="text/csv", ) @expose("/view-entries/<int:pk>") def view_entries(self, pk): """View form entries""" form = self.get_one(str(pk)) entries = FormEntry.query.filter_by(form=form) paginator = paginate_with_args(entries) return self.render( "oy_admin/form-entries.html", form=form, paginator=paginator, val_proc=_process_field_value, )
"meta_description", "has_auto_desc", "keywords", ), form_excluded_columns=("site", "created", "updated", "versions", 'author'), form_extra_fields={ 'status': SelectField(label=lazy_gettext('Status'), choices=Displayable.STATUS_CHOICES) }) default_row_actions = (EndpointLinkRowAction( icon_class="fa fa-clock-o", endpoint='.versioning_index', title=lazy_gettext("Manage Versions"), id_arg='pk'), ) class SiteAdmin(CanellaModelView): can_view_details = True # Edit in a dialog not in a new page. edit_modal = True details_modal = True # Enable CSRF protection. form_base_class = SecureForm form_excluded_columns = ['settings'] # How many entries to display per page? page_size = 5 # Column formatters.
class Report1View(ModelView): column_extra_row_actions = [ EndpointLinkRowAction('fa fa-file glyphicon icon-file', 'report1.create_report'), ] can_create = False can_delete = False can_edit = True can_view_details = False can_export = True column_list = ('user_id', 'course', 'per_start', 'per_end') form_columns = ('user_id', 'course', 'per_start', 'per_end') column_labels = dict( user_id=u'Имя пользователя', course=u'Идентификатор курса', per_start=u'Начало промежутка', per_end=u'Конец промежутка' ) column_formatters = dict( user_id=lambda v, c, m, p: db.session.query(Users.username).filter(Users.id == m.user_id).one_or_none()[0] if m.user_id else '', per_start=lambda v, c, m, p: datetime.strftime(m.per_start, '%d.%m.%Y') if m.per_start else '', per_end=lambda v, c, m, p: datetime.strftime(m.per_end, '%d.%m.%Y') if m.per_end else '' ) column_display_pk = False @expose('/report') def create_report(self): data={} user_id = db.session.query(Report1.user_id)\ .filter(Report1.id == request.args.get('id')).one_or_none()[0] data['username'] = db.session.query(Users.username)\ .filter(Users.id == user_id).one_or_none()[0] data['lastseen'] = datetime.strftime( db.session.query(Others.event_time)\ .filter(Others.user_id == user_id)\ .order_by(Others.event_time.desc()).first()[0], '%d.%m.%Y %H:%M:%S') courses = db.session.query(EnrollmentEvents.course, EnrollmentEvents.event_time)\ .filter(and_(EnrollmentEvents.user_id == user_id, EnrollmentEvents.type == 'enrollment_activated')) data['courses'] = [] count = 1 for c in courses.all(): row = {} row['pp'] = count row['course'] = c.course count += 1 row['reg_time'] = datetime.strftime(c.event_time, '%d.%m.%Y %H:%M:%S') deact_time = db.session.query(EnrollmentEvents.event_time)\ .filter(and_(EnrollmentEvents.user_id == user_id, EnrollmentEvents.type == 'enrollment_deactivated')).first() row['deact_time'] = datetime.strftime(deact_time[0], '%d.%m.%Y %H:%M:%S') if deact_time else u'---' cert_time = db.session.query(CertificateEvents.event_time)\ .filter(and_(CertificateEvents.course == c.course, CertificateEvents.user_id == user_id)).first() row['cert_time'] = datetime.strftime(cert_time[0], '%d.%m.%Y %H:%M:%S') if cert_time else u'---' right = db.session.query(CheckAnswerEvents.event_time)\ .filter(and_(CheckAnswerEvents.type == 'problem_check', CheckAnswerEvents.success == True, CheckAnswerEvents.user_id == user_id)).all() false = db.session.query(CheckAnswerEvents.event_time)\ .filter(and_(CheckAnswerEvents.type == 'problem_check', CheckAnswerEvents.success == False, CheckAnswerEvents.user_id == user_id)).all() row['rf'] = str(len(right)) + u'/' + str(len(false)) data['courses'].append(row) #second plot plt.rcdefaults() fig, ax = plt.subplots() events = (u'Серт.', u'Пров. отв.', u'Докум.', u'Регистр.', u'Сылки', u'Навиг.', u'Видео') y_pos = range(len(events)) plot_values = ( len(db.session.query(CertificateEvents.id).filter(CertificateEvents.user_id == user_id).all()), len(db.session.query(CheckAnswerEvents.id).filter(CheckAnswerEvents.user_id == user_id).all()), len(db.session.query(DocumentEvents.id).filter(DocumentEvents.user_id == user_id).all()), len(db.session.query(EnrollmentEvents.id).filter(EnrollmentEvents.user_id == user_id).all()), len(db.session.query(LinkEvents.id).filter(LinkEvents.user_id == user_id).all()), len(db.session.query(SequenceEvents.id).filter(SequenceEvents.user_id == user_id).all()), len(db.session.query(VideoEvents.id).filter(VideoEvents.user_id == user_id).all()) ) ax.barh(y_pos, plot_values, xerr=None, align='center', color='orange', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(events) ax.invert_yaxis() ax.set_xlabel(u'Количество событий') ax.set_title(u'Количество собыий по группам') plt.savefig(os_join(app.config['REPORT_PATH'], 'plt2.png')) data['plt2_path'] = os_join(app.config['REPORT_PATH'], 'plt2.png') #third plot plt.rcdefaults() fig, ax = plt.subplots() events = (u'Докум.', u'Курс', u'Видео') y_pos = range(len(events)) plot_values = ( len(db.session.query(DocumentEvents.id).filter(DocumentEvents.user_id == user_id).all()), len(db.session.query(LinkEvents.id).filter(LinkEvents.user_id == user_id).all())+\ len(db.session.query(SequenceEvents.id).filter(SequenceEvents.user_id == user_id).all()), len(db.session.query(VideoEvents.id).filter(VideoEvents.user_id == user_id).all()) ) ax.barh(y_pos, plot_values, xerr=None, align='center', color='blue', ecolor='black') ax.set_yticks(y_pos) ax.set_yticklabels(events) ax.invert_yaxis() ax.set_xlabel(u'Количество собыий') ax.set_title(u'Предпочитаемые материалы') plt.savefig(os_join(app.config['REPORT_PATH'], 'plt3.png')) data['plt3_path'] = os_join(app.config['REPORT_PATH'], 'plt3.png') f_name = os_join(app.config['REPORT_PATH'], 'report_res.odt') if exists(f_name): remove(f_name) Renderer( os_join(app.config['REPORT_PATH'], "user_report.odt"), data, f_name, pythonWithUnoPath='/usr/bin/python3' ).run() return send_file( filename_or_fp=f_name, as_attachment=True, attachment_filename=basename(f_name), mimetype='application/vnd.oasis.opendocument.text' )
class AinView(BaseModelView): statuses = dict(Statuses.__dict__) column_filters = ('Status', 'AlienID', 'Zipcode', 'Last Step Error') named_filter_urls = True can_set_page_size = True page_size = 20 can_view_details = True create_modal = True details_modal = True edit_modal = True export_max_rows = 1000 can_export = True export_types = ['csv', 'xlsx', 'json'] #column_editable_list = ('Status',) column_exclude_list = ( 'CallID', 'CallUploadUrl', 'CallTimestamp', 'TranscribeTimestamp', 'CallTranscript', ) column_extra_row_actions = [ EndpointLinkRowAction('glyphicon glyphicon-headphones', 'audio') ] form_create_rules = [ Field('PartitionKey'), ] form_edit_rules = [ Field('Status'), ] form_args = dict( Status=dict(label='Status', validators=[DataRequired()]), PartitionKey=dict(label='AlienID', validators=[DataRequired()]), ) column_labels = dict( PartitionKey='Alien ID', LastErrorStep='Last Error Step', CallTranscript='Call Transcript', CallID='Call ID', LastModified='Last Modified', CallTimestamp='Call Timestamp', TranscribeTimestamp='Transcribe Timestamp', CallUploadUrl='Call Upload Url', ) def get_pk_value(self, model): return model.PartitionKey def scaffold_list_columns(self): return [ 'PartitionKey', 'Status', 'Confidence_location', 'City', 'State', 'Zipcode', 'day', 'hour', 'minute', 'month', 'year', 'CallTranscript', 'LastErrorStep', 'CallID', 'CallUploadUrl', 'CallTimestamp', 'LastModified', 'TranscribeTimestamp', ] def scaffold_sortable_columns(self): return None def init_search(self): return False def scaffold_filters(self, name): return [EqualFilter(name, name)] def get_list(self, page, sort_field, sort_desc, search, filters, page_size=20): if len(filters) > 0: filter_col, filter_val = filters[0][1], filters[0][2] results = db.query(filter_col, filter_val, page_size) else: results = db.raw_table(limit=page_size) results = list(results) return len(results), results def get_one(self, id): return db.get_ain(id) def delete_model(self, model): return db.delete_ain(model.PartitionKey) def create_model(self, form): ain = form.PartitionKey.data db.upload_new_requests([ain]) return self.get_one(ain) def update_model(self, form, model): status = form.Status.data model.Status = status db._update_entity(model) return True def scaffold_form(self): class AinForm(BaseForm): PartitionKey = StringField('Alien ID') Status = SelectField('Status', choices=self.statuses) CallTranscript = StringField('CallTranscript') return AinForm @action('reset_status', 'Reset Status', 'Are you sure you want to reset the selected records?') def action_upload(self, ids): try: flash('Not implemented yet') except Exception as ex: flash('Failed to reset the status', 'error')