The background,

In our work, we often need to build some web-based projects, such as internal test platform, operation and maintenance system, etc. This article focuses on how to quickly build a framework for a Web project using the backend Django + front-end Vue.js technology stack.

Why use Django and Vue.js?

Django is one of the most mature Web frameworks in Python. Due to the ease of use and popularity of Python, Django is the first choice for small and medium-sized web development frameworks due to its rapid development of web applications. Besides, Django has data analysis (Pandas), task queue (tasks), Restful API(Django REST framework) ), ORM(Java-like Hibernate) and many other features make it easy for users to build any site they want.

Vue.js is a popular JavaScript MVVM library. It is built with data driven and componentized ideas. Vue.js also supports features like bidirectional binding and mustache tag syntax compared to Angular.js, and provides a cleaner and easier to understand API to get up and running with vue.js quickly.

This article uses Vue. Js as a front-end framework instead of Django’s own weak template engine. Django serves as a server and provides an API interface, which makes the front and back ends completely separate and more suitable for the development and construction of single-page applications.

Ii. Relevant technology and environment used in the project

  • Operating system: Windows 10

  • Database: MySQL 5.7

  • Back end: Django 2.x framework, Python 3.x

  • Front end: / jQuery/JavaScript/HTML/CSS Vue. Js

Note: Python-related modules are installed using the PIP installer that comes with Python. For front-end related third-party packages, we use node’s built-in NPM package manager to install them.

Build a Django project

1. Go to a secure directory, open the command-line prompt CMD, and enter the following command:

django-admin startproject myproject
Copy the code

Directory structure:

2, go to the myProject directory, create a new virtual environment and activate:

cd myproject
# Virtualenv must be installed
pip install virtualenv
Create a new virtual environment
virtualenv env
Activate the virtual environment
.\env\Scripts\activate
# to install django
pip install django
Install required modules in advance
pip install requests
Copy the code

Tags to activate the virtual environment:

3. Create an app:

python manage.py startapp myapp
Copy the code

Directory structure:

In myProject Settings. Py, replace the default sqlite3 database with our mysql database:

# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql'.'NAME': 'myproject'.'USER': 'root'.'PASSWORD': 'admin'.'HOST': '127.0.0.1',}}# Tips
Change the user and password to your own, and make sure you have a database named myProject
Copy the code

Add the app to the installed_apps list:

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

Copy the code

In the app directory models.py we simply write a model as follows:

from django.db import models

# Create your models here.
class Book(models.Model):
    book_name = models.CharField(max_length=64)
    add_time = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.book_name
Copy the code

There are only two fields, the title book_name and the add time add_time. If no primary key is specified, Django will automatically add an increment id as the primary key

Enter the following command on the command line window:

# installation mysqlclient
pip install mysqlclient
# Database migration
python manage.py makemigrations myapp
python manage.py migrate
Copy the code

Navicat Premium 12: The book table has been created automatically.

Show_books returns a list of all books (JsonResponse returns json data that can be recognized by the front end). Add_book accepts a GET request. Adds a book to the database

from django.shortcuts import render

# Create your views here.
# Need to import related modules
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.core import serializers
import requests
import json

from .models import Book

@require_http_methods(["GET"])
def add_book(request):
    response = {}
    try:
        book = Book(book_name=request.GET.get('book_name'))
        book.save()
        response['msg'] = 'success'
        response['error_num'] = 0
    except  Exception as e:
        response['msg'] = str(e)
        response['error_num'] = 1

    return JsonResponse(response)

@require_http_methods(["GET"])
def show_books(request):
    response = {}
    try:
        books = Book.objects.filter()
        response['list']  = json.loads(serializers.serialize("json", books))
        response['msg'] = 'success'
        response['error_num'] = 0
    except  Exception as e:
        response['msg'] = str(e)
        response['error_num'] = 1

    return JsonResponse(response)
Copy the code

As you can see, with the help of ORM, our interface doesn’t actually need to organize the SQL code itself

First of all, the original author also uses GET request to add books, so I do not have the idea of changing it to post request, since there is a friend mentioned, I would like to say here if you want to change the method of adding books to POST step. First, modify the contents of views.py in the app directory based on the above code:

# @require_http_methods(["GET"])
# @ require_http_methods ([" POST "])
def add_book(request):
    response = {}
    try:
        # book = Book(book_name=request.GET.get('book_name'))
        book = Book(book_name=request.POST.get('book_name')) # modified
        book.save()
        response['msg'] = 'success'
        response['error_num'] = 0
    except  Exception as e:
        response['msg'] = str(e)
        response['error_num'] = 1

    return JsonResponse(response)
Copy the code

After modification, if the add_book interface is directly tested on Postman software, 403 error will appear, as shown in the figure:

from django.urls import path,re_path
# Import myApp views file
from . import views

urlpatterns = [
    re_path(r'add_book$', views.add_book),
    re_path(r'show_books$', views.show_books)
]
Copy the code

In addition, we need to add the urls under app to the urls under project to complete the routing:

from django.contrib import admin
from django.urls import path,re_path
from django.conf.urls import url, include
import myapp.urls

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^api/', include(myapp.urls)),
]
Copy the code

8, enter the command to start the server:

python manage.py runserver
Copy the code

Test interface method one: through the browser, because the request is a get request, so you can directly on the browser directly see the results of the server returns Direct input http://localhost:8000/api/show_books in your browser’s address bar, you will see the effect of the picture below:

Directly in your browser’s address bar enter http://localhost:8000/api/add_book? If book_name=test, you will see the following image:

Test interface mode 2

Let’s test the two interfaces we just wrote with Postman:

Add_book interface:

Show_books interface:

Learning links:

  • Postman use tutorial detailed

  • How to use Postman The most comprehensive tutorial

  • Postman installation and use

Iv. Build vue.js front-end project

Prerequisites: NODE is installed and the NPM package manager is shipped with it

1. Install the Vue-CLI scaffolding tool with NPM (vue-CLI is the official scaffolding tool, which can help you quickly build the framework of the VUE project) :

npm install -g vue-cli
Copy the code

After the installation, create a new front-end project directory under the root of the project:

vue-init webpack appfront  // Install vue-Router, we need it for the front-end routing
Copy the code

Now we can see that the entire file directory structure looks like this:

2. Include the entry file main.js and the entry component app.vue under the directory SRC. A file with the suffix vue is a single file component defined by the vue. js framework. The content in the tag can be interpreted as HTML like page structure content, the content in the tag is JS methods, data content, and the content in the CSS style:

Install and introduce the Element UI and AXIOS

Start by installing the Element UI and AXIOS on the command line

npm install element-ui
npm install axios
Copy the code

In SRC /main.js, add the following code:

/ / introduce element - the UI
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

/ / introduce axios
import axios from 'axios'
Vue.prototype.$axios = axios

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  axios,
  components: { App },
  template: '<App/>'
})

Copy the code

Create a new component called home.vue in the SRC/Component folder and use the API you wrote on Django to add and display books.

<template> <div class="home"> <el-row display="margin-top:10px"> <el-input V-model ="input" placeholder=" placeholder "> style="display:inline-table; width: 30%; float:left"></el-input> <el-button type="primary" @click="addBook()" style="float:left; margin: 2px;" > </ button> </ button> </ button> </ button> </ button> </ button> </ button> </ button> 100%" border> <el-table-column prop="id" label=" id" min-width="100"> <template slot-scope="scope"> {{scope.row.pk}} </template> </el-table-column> <el-table-column prop="book_name" label=" title "min-width="100"> <template slot-scope="scope"> {{ scope.row.fields.book_name }} </template> </el-table-column> <el-table-column prop="add_time" <template slot-scope="scope"> {{scope.row.fields. Add_time}} </template> </el-table-column> </el-table> </el-row> </div> </template> <script> export default { name: 'home', data () { return { input: '', bookList: [], } }, mounted: function() { this.showBooks() }, methods: {{same () this. $axios. Get (' http://127.0.0.1:8000/api/add_book? book_name=' + this.input) .then((res) => { // console.log(res) var res = res.data; If (res.error_num == 0) {this.showbooks ()} else {this.$message.error(' failed to add books, Try ') console.log(res[' MSG '])}})}, ShowBooks () {this. $axios. Get (' http://127.0.0.1:8000/api/show_books'). Then ((res) = > {var res = res. Data; // console.log(res) if (res.error_num == 0) {this.booklist = res['list']} else {this.$message.error(' failed to query books ') console.log(res['msg']) } }) } } } </script> <! -- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>Copy the code

5. If the list fails to capture data, it may be a cross-domain problem. Open browser Console to confirm:

In this case, we need to inject headers into the Django layer and use Django’s third-party package Django-comms-headers to solve cross-domain problems:

pip install django-cors-headers
Copy the code

Modify the Settings. Py

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware'.'django.contrib.sessions.middleware.SessionMiddleware'.'corsheaders.middleware.CorsMiddleware'.# New middleware
    '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
Copy the code

6. In the front-end project directory, enter NPM run dev to start the server provided by the node. The browser automatically opens, and we can see the page:

7. In the front-end engineering directory, type NPM run build. If there are no errors in the project, you can see that all the components, CSS, images, etc are automatically packaged into the Dist directory by WebPack:

Integrate Django with Vue.js

So far we have created and written the Django back end and the Vue.js front end, but they are actually running on their own servers, which is inconsistent with our requirements. So we need to point Django’s TemplateView at the front-end dist file we just generated.

As far as I’m concerned, if you want to implement a separate project, you don’t need to look at the following: Vue.js implements the front end of the project, and Django implements the back end, providing the API.

1. Go to the urls.py directory in the project directory and use the generic view to create the simplest template controller that returns index.html directly when accessing “/” :

from django.contrib import admin
from django.urls import path,re_path
from django.conf.urls import url, include
import myapp.urls
from django.views.generic import TemplateView # additional

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^api/', include(myapp.urls)),
    re_path(r'^$', TemplateView.as_view(template_name="index.html")), # additional
]

Copy the code

The previous step uses Django’s template system, so you need to configure the template so Django knows where to find index.html. Under settings.py in the project directory:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates'.'DIRS': ['appfront/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',],},},]Copy the code

3. We also need to configure the search path for static files. Under settings.py in project directory:

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

4. After the configuration is complete, we enter the command python manage.py runserver in the project directory, and we can see our front end page displayed in the browser:

Note: the service port is already 8000 for the Django service, not 8080 for the Node service

Six, deployment,

Because of python’s cross-platform nature, it is theoretically possible to run the project by having all dependencies installed on the server and copying the project directory directly to the server. Just one point: If you have nginx as a reverse proxy for your project, set all static file paths in nginx to point to the static file URL configured in your Django project. Set the url path in settings.py:

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'
Copy the code

Seven, other

The source code of the example project can be downloaded by clicking the link below:

Github.com/xyyojl/djan…

Finally, special thanks to the original author. ╂ Nomad writes a blog that integrates Django + vue. js framework to quickly build web projects. The entire blog post references the original blog written by the original author and rewrites the instance project with the latest technology stack, which is different from the original one.