NEURO-LEARN

Django+Vue前后端分离开发

2019-08-19  本文已影响0人  ELVENITO

未经许可请勿转载。
Please do not reprint this article without permission.

Project repository - NEURO-LEARN

Django+Vue+Celery

Environment

Build Project

$ django-admin startproject neurolearn
$ cd neurolearn
$ python manage.py startapp backend
'NAME': 'neurolearn'
'USER': 'root'
'PASSWORD': 'root'
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'neurolearn',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '127.0.0.1',
    }
}
$ python manage.py makemigrations backend
$ python manage.py migrate
$ python manage.py runserver
$ npm install -g vue-cli
$ npm view vue-cli version // check the package version
$ vue-init webpack frontend
$ cd frontend
$ npm install # install dependencies
$ npm run build # build project
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'backend',
]
$ python manage.py createsuperuser
# username: root
# email: leibingye@outlook.com
# password: root
# localhost:8000/admin/

References
整合Django+Vue.js框架快速搭建web项目
后端Django+前段Vue.js快速搭建项目
vue使用npm run build命令打包项目

Architecture Design

architecture_design_web.png

Integrate Vue into Django

from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', TemplateView.as_view(template_name="index.html")),
]
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['frontend/dist'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
# LANGUAGE_CODE = 'en-us'
# TIME_ZONE = 'UTC'
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
# add at the end of the file
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "frontend/dist/static")
]
$ python manage.py runserver
$ cd frontend
$ npm run build
$ cd frontend
$ npm run dev
$ pip install django-cors-headers
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware', # added
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CORS_ORIGIN_ALLOW_ALL = True # added

References
Vue+Django+MySQL搭建指南(个人全栈快速开发)
我如何使用Django+Vue.js快速构建项目
Django与Vue之间的数据传递

Integrate Celery into Django

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'backend',
    'djcelery',
]
import djcelery
djcelery.setup_loader()

BROKER_HOST = "localhost"
BROKER_PORT = 5672
BROKER_USER = "guest"
BROKER_PASSWORD = "guest"
BROKER_VHOST = "/"
[djcelery]
    celery
    celerybeat
    celerycam
    celeryd
    celeryd_detach
    celeryd_multi
    celerymon
    djcelerymon
from celery.decorators import task

@task
def add(x, y):
  return x + y
# @ is the decorator, making the add function a callback function
# when calling add in a webapp, the add function doesn't execute immediately
# instead the function name and parameters will be packed as a message and
# sent to the queue, then the worker will process these messages one by one
$ python manage.py migrate
$ python manage.py celeryd -l info
$ python manage.py shell
>>> from backend.tasks import add
>>> r = add.delay(3, 5)
>>> r.wait()
8

References
使用django+celery+RabbitMQ实现异步执行


NEURO-LEARN-WEB

UI Design

User Interface

Vue and Element-UI

$ npm install
$ npm install node-sass // if needed
$ npm run dev // serve with hot reload at localhost:8080
$ npm run build // build for Django to serve at localhost:8000
Note: 
The template is develped using element-ui 1.4, which is out of date. Use element-ui 2.7 when develop frontend.
//eslint-disable-line
$ npm install --save-dev sass-loader style-loader css-loader
this.$router.replace({
  path: '/submissions',
  component: resolve => require(['@/pages/analysis/submissions'], resolve)
})

References
Element-UI Documentation

Data Transaction

# mysql -u root -p
# password: root
mysql> use neurolearn_dev;
mysql> select * from backend_submissions_demo

references
Django模型Model自定义表名和字段列名
axios全攻略
vue $http请求服务
Vue:axios中的POST请求传参问题
Vue + Django

File Uploading

url(r'upload_data$', views.upload_data, ),
class Data_Demo(models.Model):
    data_id = models.DateTimeField('Edit the date', auto_now=True)
    data_name = models.CharField(max_length=64)
    data_path = models.CharField(max_length=128)

    def __unicode__(self):
        return self.task_id
@require_http_methods(['POST'])
def upload_data(request):
    response = {}
    try:
        obj = request.FILES.get('test')
        data = Data_Demo()
        data.data_name = 'test'
        data.data_path = obj.name
        data.save()
        handle_uploaded_file(obj)
        
        response['msg'] = 'success'
        response['error_num'] = 0
    
    except Exception as e:
        response['msg'] = str(e)
        response['error_num'] = 1

    return JsonResponse(response)

def handle_uploaded_file(f):
    try:
        path = 'data/'
        if not os.path.exists(path):
            os.makedirs(path)
        else:
            file_name = str(path + f.name)
            destination = open(file_name, 'wb+')
            for chunk in f.chunks():
                destination.write(chunk)
            destination.close()
    except Exception as e:
        print(e)
    return f.name, path
<template>
  <div style="background-color: #FFFFFF; margin: 14px; padding: 14px">
    <el-upload
      class="upload-demo"
      action="http://127.0.0.1:8000/api/upload_data"
      name="test"
      :on-change="handleChange"
      :on-success="uploadSuccess"
      :file-list="fileList">
      <el-button size="small" type="primary">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
    </el-upload>
  </div>
</template>

<script>
export default {
  data () {
    return {
      fileList: []
    }
  },
  methods: {
    handleChange (file, fileList) {
      this.fileList = fileList.slice(-4)
    },
    uploadSuccess (response) {
      console.log(response.error_num, response.msg)
    }
  }
}
</script>

references
Django快速实现文件上传
Element-UI Upload上传
Django多文件上传,只能保存最后一个文件
Django文件上传到后台的三种方式

File Downloading

@require_http_methods(["GET"])
def download_templates(request):
    response = {}
    template_type = request.GET.get('template_type')

    template_file=open('templates/' + template_type + '.zip', 'rb')
    response =FileResponse(template_file)
    response['Content-Type']='application/octet-stream'
    response['Content-Disposition']='attachment;filename=\"' + template_type + '.zip\"'
    return response
<a href="http://127.0.0.1:8000/api/download_templates?template_type=dataset_templates"></a>

Visualization

import io
from PIL import Image

@require_http_methods(["GET"])
def show_roc(request):
    response = {}
    task_id = request.GET.get('task_id')

    buf = io.BytesIO()
    img = Image.open('results/' + task_id + '/190514_ROC_curve_rfe_svm_test_data.png')
    img.save(buf, 'png')

    return HttpResponse(buf.getvalue(), 'image/png')
<img :src="'http://127.0.0.1:8000/api/show_roc?task_id=' + this.taskid" style="width: 700px">
// Source module
onRowClick (row) {
      this.$router.push({
        path: '/analysis/viewer',
        query: {taskid: row.fields.task_id}
      })
    }

// Destination module
taskid: this.$route.query.taskid,

Service

Celery and RabbitMQ

@task
def new_ml_task():
    test_task()
    return
@require_http_methods(["POST"])
def new_task(request):
    response = {}
    postBody = json.loads(request.body)
    try:
        task = Submissions_Demo(
            task_name=postBody.get('task_name'),
            task_type=postBody.get('task_type'),
            train_data=postBody.get('train_data'),
            test_data=postBody.get('test_data'),
            label=postBody.get('label'),
            feat_sel=postBody.get('feat_sel'),
            estimator=postBody.get('estimator'),
            cv_type=postBody.get('cv_type'),
            note=postBody.get('note'),
            verbose=postBody.get('verbose'),
            task_status='Submitted',
            task_result=''
        )
        task.save()

        # create new celery task
        new_ml_task.delay()
        ...
$ python manage.py celeryd -l info

Databases

Deployment

Local Server

GitHub

上一篇下一篇

猜你喜欢

热点阅读