zoukankan      html  css  js  c++  java
  • Build web app with Vue.js and Django

    Django是一个基于python开发,且强大好用的web框架。虽然Django Model的设计优美、令人赞叹不已,但其Template部分却一直饱受争议。近年来,前后端分离的开发模式逐渐成为web应用开发的主流开发模式,使用Django也可以做到前后端分离开发。本文介绍如何构建Vue.js与Django并存,实现前后端分离的方法。

    示例项目名为vue_django

    系统和环境

    • Ubuntu 18.04 LTS
    • Python 3.6.10
    • Django 3.0.7-final
    • Node.js 8.10.0
    • MySQL 5.7.30
    • Docker 19.03.11

    利用django构建基本框架

    >>> django-admin startproject vue_django
    

    结构如下

    >>> tree
    .
    ├── manage.py
    └── vue_django
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py
    

    进入项目根目录,创建一个名为backend的django app作为项目后端

    >>> cd vue_django
    >>> python manage.py startapp backend
    # 初始化数据库
    >>> python manage.py migrate
    

    结构如下:

    .
    ├── backend
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── manage.py
    └── vue_django
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py
    

    在settings.py里添加backend app

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'backend',
    ]
    

    使用Vue.js创建一个Vue项目作为前端

    # 使用npm安装vue-cli脚手架工具
    >>> npm install -g vue-cli
    >>> vue-init webpack frontend
    

    此时,项目根目录有三个文件夹,分别为backend、frontend和vue_django。接下来我们使用webpack打包Vue.js项目。

    >>> cd frontend
    >>> npm install
    >>> npm run build
    

    构建完成后,frontend目录下会多出一个名为dist的新目录,里面有一个index.html和一个目录staticstatic存放前端所需静态文件。

    使用Django的通用视图TemplateView

    找到项目根路由配置vue_django/urls.py,使用通用视图创建最简单的模板控制器,访问/时直接返回index.html。

    ...
    from django.views.generic import TemplateView
    from django.urls import path, include
    ...
    
    urlpatterns = [
          ... ,
          path(r'', TemplateView.as_view(template_name="index.html")),
          path('', include('backend.urls'))
    ]
    

    同时,在backendapp下新建路由urls.py,在里面填充api路由。

    配置Django项目的模板搜索路径

    上一步使用了Django的模板系统,所以需要配置模板,使Django知道从哪里找到index.html。
    打开vue_django/settings.py,找到TEMPLATES配置项,修改如下:

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            # 修改DIRS
            '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',
                ],
            },
        },
    ]
    

    注意这里的frontend是Vue.js项目目录,dist则是运行npm run build构建出的index.html与静态文件夹static的父级目录。这时我们启动Django项目,访问/则可以访问index.html,但静态文件都是404错误。下面解决这个问题。

    配置静态文件搜索路径

    打开vue_django/settings.py,在文件最后添加STATICFILES_DIRS配置项:

    # Add for vuejs
    
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, "frontend/dist/static"),
    ]
    

    此时再次启动Django,访问/则可以看到Vue.js自带的Hello World页面了。

    这里遇到了新问题:使用Vue.js的开发环境脱离了Django环境,如果要访问Django环境的API,就会出现跨域问题。有两种解决方案:一种是在Vue.js层上做转发(proxyTable);另一种是在Django层注入header,这里使用后者,用python第三方包django-cors-headers来解决跨域问题。

    >>> pip install django-cors-headers
    

    修改vue_django/settings.pyMIDDLEWARE配置,添加corsheaders中间件。

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        # 添加corsheaders中间件
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    

    这里要注意中间件添加顺序,列表是有序的。接下来修改vue_django/settings.py,在文件末尾添加STATIC_ROOT = os.path.join(BASE_DIR, "static")

    至此,前后端分离框架搭建完成。我们可以到服务器上部署该web app了。无论什么web框架,都需要一个web服务器把app跑起来。常见的解决方案有apache、nginx。这里介绍nginx+uwsgi的解决方案。当我们拉起应用后,完整的组件堆栈如下所示:

    web-client <-> web-server <-> socket <-> uwsgi <-> django
    

    安装nginx和uwsgi (以debian/ubuntu为例)

    cd ~
    sudo apt install nginx uwsgi uwsgi-plugin-python uwsgi-plugin-python3 python3-dev python-dev
    

    生成一份名为foobar.py的测试文件,填入以下内容

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    def application(env, start_response):
          start_response('200 OK', [('Content-Type', 'text/html')])
          return [b"Hello World"]
    

    执行以下命令,启动uwsgi。

    uwsgi --http-socket :8000 --plugin python --wsgi-file foobar.py
    

    访问ip:8000即可看到Hello World字样。此时意味着以下组件堆栈是有效的:

    web-client <-> uWSGI <-> Python
    

    把项目clone到服务器后,配置好数据库设置,执行:

    python manage.py migrate
    python manage.py runserver 0.0.0.0:8000
    

    访问ip:8000,能看到在开发环境完成的demo。此时意味着以下组件堆栈是有效的:

    web-client <-> uWSGI <-> Django
    

    通过下面的命令测试vue_django/wsgi.py的功能:

    uwsgi --http-socket :8000 --plugin python3 --module vue_django.wsgi:application
    

    注意:这一步操作有很多坑点。uwsgi默认使用python2,如果报错,可以尝试把--plugin后的python3更换为python。如果不使用--plugin,则无法使用--module

    测试Nginx功能

    systemctl start nginx.service
    

    访问ip,可以看到来自nginx的一条"欢迎使用nginx"的消息。此时意味着以下组件堆栈是有效的:

    web-client <-> web-server
    

    复制uwsgi_params文件到项目根目录下,该文件位于uwsgi所在目录下(可以通过whereis uwsgi查看)。在/etc/nginx/sites-available目录下创建一个名为mysite_nginx.conf的文件:

    # the upstream component nginx needs to connect to
    upstream django {
        # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
        server 127.0.0.1:8001; # for a web port socket (we'll use this first)
    }
    
    # configuration of the server
    server {
        # the port your site will be served on
        listen      8000;
        # the domain name it will serve for
        server_name example.com; # substitute your machine's IP address or FQDN
        charset     utf-8;
    
        # max upload size
        client_max_body_size 75M;   # adjust to taste
    
        # Django media
        location /media  {
            alias /path/to/your/mysite/media;  # your Django project's media files - amend as required
        }
    
        location /static {
            alias /path/to/your/mysite/static; # your Django project's static files - amend as required
        }
    
        # Finally, send all non-media requests to the Django server.
        location / {
            uwsgi_pass  django;
            include     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed
        }
    }
    

    该conf文件指示Nginx从文件系统提供媒体和静态文件,并处理Django请求。创建一个从/etc/nginx/sites-enabled到该文件的软连接,以便Nginx可以找到它。

  • 相关阅读:
    web.xml 中的listener、 filter、servlet 加载顺序及其详解
    AOP概念的理解
    webx学习总结
    如何设计编制软件测试用例(一~三)
    冒烟测试小结(转载)
    在web.xml不认<taglib>解决办法
    document.domain 跨域问题【转】
    判断图片是否加载完成
    指定步长中间值
    关于 contentWindow, contentDocument
  • 原文地址:https://www.cnblogs.com/JHSeng/p/13064756.html
Copyright © 2011-2022 走看看