数智教育数据可视化创新大赛总结

数智教育数据可视化创新大赛总结

后端

使用Django Rest Framework中规中矩的api,memcached简单配置

  • 环境搭建

  • 数据库配置

    • 考虑数据整体不会有太大变动,可能需要从本地开发环境直接迁移到线上服务器,所以使用docker搭载postgres的方法,上线后可直接将docker镜像进行恢复然后迁移数据

    • docker 镜像备份方法

      1
      2
      3
      4
      1. docker save [container_name] > bak.tar # save as tar
      2. docker load -i ./bak.tar # 恢复container
      3. 进入postgre创建database然后执行如下
      4. cat your_dump.sql | docker exec -i your-db-container psql -U tianchiuser tianchidb
  • 数据迁移

    • 使用runpython在migration中运行自定义脚本

      • 编写def fun(apps, schema_editor)函数,通过apps.get_model()获取数据模型
      • 在operations中加入 migrations.RunPython(fun, reverse_code=migrations.RunPython.noop)
      • reverse_code=migrations.RunPython.noop使用reverse_code去定义回滚时使用的方法,此处会忽略runpython产生的任何修改,直接回滚
    • 回滚migration 参考链接

      • python manage.py migrate [app_name] [migration_name]将某个app的migrations回滚到某个migration文件为止
      • 合并migration树
        1. ./manage.py migrate —fake [app_name] zero 回滚全部migrate,但是保留数据
        2. 删除所有migration文件
        3. ./manage.py makemigrations 重新生成migration文件
        4. ./manage.py migrate —fake-initial 重新应用合并的migration 文件
      • python manage.py showmigrations可以查看当前已应用的migration
    • Postgres 中创建用户

      1
      2
      3
      4
      psql
      postgres# CREATE USER xxxx1 WITH PASSWORD 'xxxx';
      postgres# CREATE DATABASE xxxx2;
      postgres# GRANT ALL PRIVILEGES ON DATABASE xxxx2 to xxxx1;
  • 缓存配置(memcached) 参考文档

    • settings配置

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      CACHES = {
      'default': {
      'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
      'LOCATION': '127.0.0.1:11211',
      }
      }

      INSTALLED_APPS = [
      ...,
      'django_extensions',
      ]

      REST_FRAMEWORK_EXTENSIONS = {
      'DEFAULT_CACHE_KEY_FUNC': 'utils.cache_funcs.calculate_cache_key'
      } # 使用自定义的calculate_cache_key函数

      # 通过请求的url进行缓存
      def calculate_cache_key(view_instance, view_method,
      request, args, kwargs):
      url = '{}?'.format(request.path)
      for key in request.query_params:
      url += '{}={}&'.format(key, request.query_params[key])
      return url
    • 使用rest_framework_extensions提供的@cache_response([x seconds]])装饰器进行view的缓存

前端

使用 Ant Design Pro脚手架,Umi & Dva

  • Umi 要点

    • umi 里约定 mock 文件夹下的文件或者 page(s) 文件夹下的 _mock 文件即 mock 文件
    • 对于整个系统来说,请求接口是复杂并且繁多的,为了处理大量模拟请求的场景,我们通常把每一个数据模型抽象成一个文件,统一放在 mock 的文件夹中,然后他们会自动被引入。
    • 当本地开发完毕之后,修改config.js中的proxy配置
    • umi with dva
      • 按目录约定注册 model,无需手动 app.model
      • 文件名即 namespace,可以省去 model 导出的 namespace key
      • 无需手写 router.js,交给 umi 处理,支持 modelcomponent 的按需加载
      • 内置 query-string 处理,无需再手动解码和编码
      • 内置 dva-loading 和 dva-immer,其中 dva-immer 需通过配置开启
      • 开箱即用,无需安装额外依赖,比如 dva、dva-loading、dva-immer、path-to-regexp、object-assign、react、react-dom 等
  • Dva

    • State:一个对象,保存整个应用状态

    • View:React 组件构成的视图层

    • Action:一个对象,描述事件

    • connect 方法:一个函数,绑定 State 到 View,用于建立state 和 props的映射

    • dispatch 方法:一个函数,发送 Action 到 State,被 connect 的 Component 会自动在 props 中拥有 dispatch 方法。

    • model 对象属性

      • namespace: 当前 Model 的名称。整个应用的 State,由多个小的 Model 的 State 以 namespace 为 key 合成

      • state: 该 Model 当前的状态。数据保存在这里,直接决定了视图层的输出

      • reducers: Action 处理器,处理同步动作,用来算出最新的 State

      • effects:Action 处理器,处理异步动

        • 1
          2
          3
          4
          function *addAfter1Second(action, { put, call }) {
          yield call(delay, 1000);
          yield put({ type: 'add' });
          }
        • Effect 是一个 Generator 函数,内部使用 yield 关键字,标识每一步的操作(不管是异步或同步)。

        • call:执行异步函数

        • put:发出一个 Action,类似于 dispatch

  • DOM 和 BOM

    • window对象对应着浏览器窗口本身,这个对象的属性和方法通常被称为BOM

    • D(文档)可以理解为整个Web加载的网页文档,O(对象)可以理解为类似window对象只来的东西,可以调用属性和方法,这里我们说的是document对象,M(模型)可以理解为网页文档的树形结构,DOM树由节点构成

    • Window对象包含属性:document、location、navigator、screen、history、frames

      Document根节点包含子节点:forms、location、anchors、images、links

    • BOM的核心是window,而window对象又具有双重角色,它既是通过js访问浏览器窗口的一个接口,又是一个Global(全局)对象

    • document对象:实际上是window对象的属性,document == window.document为true,是唯一一个既属于BOM又属于DOM的对象

  • Suspense 相关 参考文章

    • 懒加载const ScoreLineChart = React.lazy(() => import('./ScoreLineChart'));

    • 1
      2
      3
      <Suspense fallback={<div>Loading...</div>}>
      <ScoreLineChart />
      </Suspense>
    • 使用懒加载的组件必须放入suspense中

    • 未使用懒加载的组件不能放入suspense中,否则可能导致所挂载的dom没有渲染出来而导致报错

  • constructor.name不要用于做为判断的条件,因为webpack后会翻译为其他名字

部署 webpack

Umi build + nginx + docker实现

  • 基于docker的打包和发布真的是很方便的,虽然在项目中使用的深度还不是很深,仅用了一些皮毛

  • webpack 打包时可用hush防止缓存不刷新带来的报错 参考链接

    1
    2
    3
    4
    5
    6
    module.exports = {
    //...
    output: {
    filename: '[name].bundle.js'
    }
    };
  • cdn 加速还是很有用的 免费cdn加速

总结

  • 官方文档要仔细阅读
  • 不要重复造轮子
  • 皮毛只能解决问题,但不能理解问题

  • 代码规范还是要注重一下..虽然本次比赛比较赶没有任何规范

0%