DTCLOUD+AMIS 快速实现图表应用

前言

DTCLOUD 在低代码开发中,有着很多优势,这里不做过多的阐述,但是在图表方面还是有相对不足,虽然自带了一些图表,也可以通过嵌入 VUE 或 H5 等方式嵌入图表,也有一些其他解决方法,总归有一些不足之处,作为一个对前端不感冒的人,总希望能够找到一个 方便快捷的方式来解决国内常用的图表展示,经过本人各种对比和测试,终于发现一种纯后 端方便使用的技术,就是百度开源的 amis 低代码前端框架。
以下内容来源于 amis 网站。
amis 是一个低代码前端框架,它使用 JSON 配置来生成页面,可以减少页面开发工作量,极大提升效率。
建立 amis 的初衷:对于大部分常用页面,应该使用最简单的方法来实现,甚至不需要学习前端框架和工具。
为了实现用最简单方式来生成大部分页面,amis 的解决方案是基于JSON 来配置,它的独特好处是:
不需要懂前端: 在百度内部, 大部分 amis 用户之前从来没写过前端页面,也不会JavaScript,却能做出专业且复杂的后台界面,这是所有其他前端 UI 库都无法做到的;
不受前端技术更新的影响:百度内部最老的 amis 页面是 6 年多前创建的,至今还在使用,而当年的 Angular/Vue/React 版本现在都废弃了,当年流行的 Gulp 也被Webpack 取代了,如果这些页面不是用 amis,现在的维护成本会很高;
享受 amis 的不断升级:amis 一直在提升细节交互体验,比如表格首行冻结、下拉框大数据下不卡顿等,之前的 JSON 配置完全不需要修改;
可以完全使用可视化页面编辑器来制作页面:一般前端可视化编辑器只能用来做静态原型,而amis 可视化编辑器做出的页面是可以直接上线的。
amis 的其它亮点
提供完整的界面解决方案:其它 UI 框架必须使用 JavaScript 来组装业务逻辑,而 amis 只需 JSON 配置就能完成完整功能开发,包括数据获取、表单提交及验证等功能,做出来的页面不需要经过二次开发就能直接上线;
大量内置组件(120+),一站式解决:其它 UI 框架大部分都只有最通用的组件,如果遇到一些稍微不常用的组件就得自己找第三方,而这些第三方组件往往在展现和交互上不一致,整合起来效果不好,而 amis 则内置大量组件,包括了富文本编辑器、代码编辑器、diff、条件组合、实时日志等业务组件,绝大部分中后台页面开发只需要了解 amis 就足够了;
支持扩展:除了低代码模式,还可以通过自定义组件来扩充组件,实际上 amis 可以当成普通 UI 库来使用,实现 90% 低代码,10% 代码开发的混合模式,既提升了效率,又不失灵活性;
容器支持无限级嵌套:可以通过嵌套来满足各种布局及展现需求;
经历了长时间的实战考验:amis 在百度内部得到了广泛使用,在 6 年多的时间里创建了 5 万页面,从内容审核到机器管理,从数据分析到模型训练,amis 满足了各种各样的页面需求,最复杂的页面有超过 1 万行 JSON 配置。

amis 不适合做什么?
使用 JSON 有优点但也有明显缺点,在以下场合并不适合 amis:
大量定制 UI:JSON 配置使得 amis 更适合做有大量常见 UI 组件的页面,但对于面向普通客户(toC)的页面,往往追求个性化的视觉效果,这种情况下用 amis 就不合适,实际上绝大部分前端 UI 组件库也都不适合,只能定制开发。
极为复杂或特殊的交互:
有些复杂的前端功能,比如 可视化编辑器,其中有大量定制的拖拽操作,这种需要依赖原生 DOM 实现的功能无法使用 amis。

一个简单示例

以公司的一个热力图应用来说,我可以通过简单的低代码实现两个数据的柱状图显示, 一个是设备当前人数,一个是设备历史人数。
图例见下:
在这里插入图片描述
相关前端代码不过 28 行,见下面截图。
在这里插入图片描述

后端只要声明路由就可使用。这里不做展示。接口数据做好后,也可以同时给其他前端 调用,实现一次开发,多端使用的功能。

如何从零开始在DTCLOUD 里面实现 amis 功能

一、安装 python 下 amis 支持包

pip install amis

二、按照新建应用的方法,新建一个 DTCLOUD 应用,本文以 dtb_amis_demo 为例子,逐步讲解。

  1. 整体目录见下图,其中 versions 目录和内容请忽略。
    在这里插入图片描述

  2. amis_json 目录,该目录存放 amis 声明文件,本 demo 存放了一个 amis_json.py 文件, 内容如下:
    在这里插入图片描述

这里稍做解释,详细的解释请见 amis 官网。
第一个 type:page,这个是顶层容器。body 表示该容器里面的内容。
第二个 type:chart,表示是 page 里面有一个 chart 要显示。
api 是接口地址。
Interval 是这个 chart 刷新时间(毫秒)。专注后端的同学是否感觉非常简单?

  1. controllers 目录,为了方便大家看起来容易学习,就只放了一个 controllers.py 文件, 实际在项目工程中,需要适当优化。

代码一:导入包和声明 amis 相关文件路径
在这里插入图片描述

代码二:声明入口路由、载入 amis 文件并赋值、返回 html
在这里插入图片描述

代码三:声明数据入口,和返回 json 数据
在这里插入图片描述

  1. manifest .py 文 件
    这个里面没有什么特别之处,常规内容就好。
  2. 声明文件,关键是 dtb_amis_demo 目录下的 init .py 文件,需要导入 controllers
    目录,而 controllers 里面的 init .py 文件,需要导入之前写好的 controllers.py 文件。

三、所有相关文件写完后,重启 DTCLOUD,安装 dtb_amis_demo 模块,然后在浏览器上输入 127.0.0.1:9099/dtb/amis_demo 就可以看到效果了。

四、集成到某个应用中。网上有相关的方法,这里不做过多解释,集成后效果见下图。

在这里插入图片描述

后言

DTCLOUD 前端如何简单化,一直是我想解决的一个问题,寻寻觅觅中,终于找到一个相对比较好的解决方案,这里感谢百度公司能开源这么好的低代码前端框架,也同时感谢公 司同仁吴超和姜振建在百忙中抽空帮我解决了几个拦路虎,amis 功能非常强大,也希望DTCLOUD 后端开发人员能通过 amis 把自己的成果展示出来,然后和产品确认是否满足产品需要的功能,自我完成应用闭环,这样的接口才能满足其他前端应用调用的需求。

注:python 的 amis 包有个 bug 会导致图表有问题,我特意把解决方法放在最后,是希望大家能完整看完整个文档,而不是就只看看开头就动手去做,也是希望咱们在做任何事情之前 能细心起来。
该方法是吴超找到的临时解决方法,暂未提交给作者。

venv->include->lib->site->packages->amis->templates->page.html
<script type="text/javascript">
	let amis_embed = amisRequire('amis/embed')
	let amisData = amis_embed.embed('#amisId', ${AmisSchemaJson}, {locale: "${locale}"});
</script>

作者:扶云星程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要使用AMis和Django结合Token实现用户认证,您可以按照以下步骤进行操作: 1. 安装Django框架和django-rest-framework库。 2. 创建一个Django应用程序并配置好数据库。您可以使用以下命令创建一个名为'myapp'的Django应用程序。 ``` django-admin startapp myapp ``` 3. 在Django项目的settings.py文件中配置应用程序和REST框架。 ```python INSTALLED_APPS = [ ... 'rest_framework', 'myapp', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], } ``` 4. 创建一个用户模型并迁移数据库。 ```python from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager class UserManager(BaseUserManager): def create_user(self, email, password=None): if not email: raise ValueError('Users must have an email address') user = self.model( email=self.normalize_email(email), ) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password): user = self.create_user( email, password=password, ) user.is_admin = True user.save(using=self._db) return user class User(AbstractBaseUser): email = models.EmailField(verbose_name='email address', max_length=255, unique=True) is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) objects = UserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] def __str__(self): return self.email def has_perm(self, perm, obj=None): return True def has_module_perms(self, app_label): return True @property def is_staff(self): return self.is_admin ``` 5. 创建一个视图函数来处理用户登录和创建新用户。 ```python from django.contrib.auth import authenticate, login from rest_framework.authtoken.models import Token from rest_framework.decorators import api_view from rest_framework.response import Response @api_view(['POST']) def login_view(request): email = request.data.get('email') password = request.data.get('password') user = authenticate(request, email=email, password=password) if user is not None: login(request, user) token, created = Token.objects.get_or_create(user=user) return Response({'token': token.key}) else: return Response({'error': 'Invalid credentials'}) @api_view(['POST']) def register_view(request): email = request.data.get('email') password = request.data.get('password') user = User.objects.create_user(email=email, password=password) token, created = Token.objects.get_or_create(user=user) return Response({'token': token.key}) ``` 6. 创建AMis页面,使用axios库发送POST请求到这些视图函数以进行用户登录和注册。 ```javascript import React, { useState } from 'react'; import axios from 'axios'; import { amis } from '@amis/core'; function LoginForm(props) { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); try { const response = await axios.post('/api/login/', { email, password }); localStorage.setItem('token', response.data.token); props.onSuccess(); } catch (error) { console.error(error); } }; return ( <form onSubmit={handleSubmit}> <div> <label htmlFor="email">Email</label> <input type="email" id="email" value={email} onChange={(e) => setEmail(e.target.value)} /> </div> <div> <label htmlFor="password">Password</label> <input type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} /> </div> <button type="submit">Login</button> </form> ); } function RegisterForm(props) { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); try { const response = await axios.post('/api/register/', { email, password }); localStorage.setItem('token', response.data.token); props.onSuccess(); } catch (error) { console.error(error); } }; return ( <form onSubmit={handleSubmit}> <div> <label htmlFor="email">Email</label> <input type="email" id="email" value={email} onChange={(e) => setEmail(e.target.value)} /> </div> <div> <label htmlFor="password">Password</label> <input type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} /> </div> <button type="submit">Register</button> </form> ); } const schema = { type: 'page', body: [ { type: 'form', title: 'Login', mode: 'horizontal', api: { method: 'post', url: '/api/login/', data: { email: '${email}', password: '${password}', }, adaptor: (payload) => ({ ...payload.data, success: true }), }, controls: [ { type: 'email', name: 'email', label: 'Email', required: true, }, { type: 'password', name: 'password', label: 'Password', required: true, }, { type: 'submit', label: 'Login', primary: true, }, ], }, { type: 'form', title: 'Register', mode: 'horizontal', api: { method: 'post', url: '/api/register/', data: { email: '${email}', password: '${password}', }, adaptor: (payload) => ({ ...payload.data, success: true }), }, controls: [ { type: 'email', name: 'email', label: 'Email', required: true, }, { type: 'password', name: 'password', label: 'Password', required: true, }, { type: 'submit', label: 'Register', primary: true, }, ], }, ], }; function App() { const [token, setToken] = useState(localStorage.getItem('token')); const handleSuccess = () => { setToken(localStorage.getItem('token')); }; const handleLogout = () => { localStorage.removeItem('token'); setToken(null); }; return ( <div> {token ? ( <div> <p>You are logged in.</p> <button onClick={handleLogout}>Logout</button> </div> ) : ( <div> <LoginForm onSuccess={handleSuccess} /> <RegisterForm onSuccess={handleSuccess} /> </div> )} <amis schema={schema} /> </div> ); } export default App; ``` 以上就是使用AMis和Django结合Token实现用户认证的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中亿丰数字科技集团有限公司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值