图书管理系统Django+Vue
配置跨域Django和Vue点击
后端
-
图书管理系统后端接口
-
1 books/models.py 中设置表
from django.db import models # Create your models here. from django.db import models class Books(models.Model): btitle = models.CharField(max_length=32) bpub_date = models.DateField() bread = models.IntegerField() bcomment = models.IntegerField() is_delete = models.BooleanField(default=False)
-
urls.py 中设置路由
-
app/urls.py子路由
from django.urls import path from . import views urlpatterns = [ path('book/', views.BooksView.as_view()), ]
-
项目下/urls.py
"""djangoProject URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.2/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path, include urlpatterns = [ path('books/', include('books.urls')), ]
-
-
book/views.py 视图函数
from django.views import View from rest_framework.utils import json from .models import * # Create your views here. class BooksView(View): def get(self, request): books = Books.objects.filter(is_delete=False) book_list = books.values('id', 'btitle', 'bpub_date', 'bread', 'bcomment') book_list = list(book_list) data = { "code": 0, "msg": "success", "books": book_list } return JsonResponse(data) def post(self, request): body_json = request.body.decode() # print(body_json) body_dict = json.loads(body_json) # btitle = body_dict.get('btitle') # print(btitle) # bpub_date = body_dict.get('bpub_date') # bread = body_dict.get('bread') # bcomment = body_dict.get('bcomment') # book = Books(btitle=btitle, bpub_date=bpub_date, bread=bread, bcomment=bcomment) # book.save() Books.objects.create(**body_dict) return JsonResponse({"code": 0, "msg": "success"}) def put(self, request): body_json = request.body.decode() body_dict = json.loads(body_json) id = body_dict.get('id') btitle = body_dict.get('btitle') bpub_date = body_dict.get('bpub_date') bread = body_dict.get('bread') bcomment = body_dict.get('bcomment') book = Books.objects.get(id=id) book.btitle = btitle book.bpub_date = bpub_date book.bread = bread book.bcomment = bcomment book.save() return JsonResponse({"code": 0, "msg": "success"}) def delete(self, request): body_json = request.body.decode() body_dict = json.loads(body_json) id = body_dict.get('id') book = Books.objects.get(id=id) book.is_delete = True book.save() return JsonResponse({"code": 0, "msg": "success"})
-
-
2.测试接口
-
测试获取所有图书接口
http://192.168.56.100:8888/books/book
-
测试创建图书接口
添加数据 { "btitle":"dsad","bpub_date":"2020-10-29","bread":100,"bcomment":10 }
-
测试修改图书接口
http://192.168.56.100:8888/books/book/
-
测试删除数据接口 逻辑删除
http://192.168.56.100:8888/books/book/
-
前端
- 图书管理vue页面
-
http/apis.js 添加后端请求路由
/* eslint-disable */ import {get, post, put, del} from './index' // 书籍管理接口 export const getBookList = (params, headers) => get("/books/book/", params, headers) export const addBook = (params, headers) => post("/books/book/", params, headers) export const editBook = (params, headers) => put("/books/book/", params, headers) export const delBook = (params, headers) => del("/books/book/", params, headers) ```
1.1 http/index.js 添加后端请求路由
/* eslint-disable */ // 第一步:实例化axios对象,简单封装 const axios = require('axios'); // 生成一个axios实例 axios.defaults.baseURL = 'http://192.168.56.100:8888'; // 设置请求后端的URL地址 axios.defaults.timeout = 10000; // axios请求超时时间 axios.defaults.withCredentials = true; axios.defaults.headers['Content-Type'] = 'application/json'; // axios发送数据时使用json格式 axios.defaults.transformRequest = data => JSON.stringify(data); // 发送数据前进行json格式化 // 第二:设置拦截器 /** * 请求拦截器(当前端发送请求给后端前进行拦截) * 例1:请求拦截器获取token设置到axios请求头中,所有请求接口都具有这个功能 * 例2:到用户访问某一个页面,但是用户没有登录,前端页面自动跳转 /login/ 页面 */ axios.interceptors.request.use(config => { // 从localStorage中获取token // let token = localStorage.getItem('token'); // 如果有token, 就把token设置到请求头中Authorization字段中 // token && (config.headers.Authorization = token); return config; }, error => { return Promise.reject(error); }); /** * 响应拦截器(当后端返回数据的时候进行拦截) * 例1:当后端返回状态码是401/403时,跳转到 /login/ 页面 */ axios.interceptors.response.use(response => { // 当响应码是 2xx 的情况, 进入这里 // debugger return response.data; }, error => { // 当响应码不是 2xx 的情况, 进入这里 // debugger return error }); /** * get方法,对应get请求 * @param {String} url [请求的url地址] * @param {Object} params [请求时携带的参数] */ export function get(url, params, headers) { return new Promise((resolve, reject) => { // debugger axios.get(url, {params, headers}).then(res => { resolve(res) }).catch(err => { reject(err) }) }) } // 第三:根据上面分装好的axios对象,封装 get、post、put、delete请求 /** * post方法,对应post请求 * @param {String} url [请求的url地址] * @param {Object} params [请求时携带的参数] **/ export function post(url, params, headers) { return new Promise((resolve, reject) => { axios.post(url, params, headers).then((res) => { resolve(res) }).catch((err) => { // debugger reject(err) }) }) } export function put(url, params, headers) { return new Promise((resolve, reject) => { axios.put(url, params, headers).then((res) => { resolve(res) }).catch((err) => { // debugger reject(err) }) }) } export function del(url, params, headers) { return new Promise((resolve, reject) => { axios.delete(url, {data: params, headers}).then((res) => { resolve(res) }).catch((err) => { // debugger reject(err) }) }) } export default axios;
-
router/index.js 添加路由
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import Books from '@/views/books/Books' import Father from "../components/Father"; import Login from "../views/Login"; Vue.use(Router) export default new Router({ routes: [ {path: '/', name: 'Books', component: Books}, // 图书增删改查 ] })
-
src\views\books\Books.vue 父组件
<template> <div> <div> <h1>图书管理系统</h1> <div style="margin: 30px;"> <button @click="addNew">新增图书</button> <BookEdit v-show='dialogVisible' :visible.sync='dialogVisible' :data='editData' @save='save' ></BookEdit> </div> <div> <table style='margin: auto; border: solid 1px black;'> <tr> <th>图书编号</th> <th>图书名字</th> <th>出版时间</th> <th>阅读数</th> <th>评论数</th> <th>操作</th> </tr> <tr v-for="(book, index) in books" :key="book.id"> <td>{{book.id}}</td> <td>{{book.btitle}}</td> <td>{{book.bpub_date}}</td> <td>{{book.bread}}</td> <td>{{book.bcomment}}</td> <td> <button @click="edit(index)">修改</button> <button @click="del(index)">删除</button> </td> </tr> </table> </div> </div> </div> </template> <script> import {getBookList, addBook, editBook, delBook} from '@/http/apis' import BookEdit from '@/components/BookEdit' export default { components: { BookEdit }, data() { return { dialogVisible: false, books: [ // { // id: 3, btitle: "...", bpub_date: "2020-08-11", bread: 100, bcomment: 50 // } ], editData: { // 编辑的内容 btitle: "", bpub_date: "", bread: 0, bcomment: 0 }, } }, methods: { addNew() { this.editData = { // 初始化 编辑内容 btitle: "", bpub_date: "", bread: 100, bcomment: 0 } this.dialogVisible = true // 显示弹框 }, // 2.获取图书列表 get() { getBookList().then((data) => { console.log(123123123123) console.log(data) // books: [{btitle: "西游记", bpub_date: "2020-08-11", bread: 100,bcomment: 50}] this.books = data.books }) }, // 3.修改或者添加图书 save() { // 根据editData中的id判断是更新还是新增 // debugger console.log(this.editData) if (this.editData.id) { // 如果有id, 修改图书 // 修改请求 let params = this.editData editBook(params).then((res) => { console.log(res) this.get() }) } else { // 增加图书 addBook(this.editData).then((res) => { this.get() }) } }, // 点击修改弹出修改页面 edit(index) { this.editData = JSON.parse(JSON.stringify(this.books[index])) // 复制this.books[index]的数据 // this.editData = this.books[index] // this.dialogVisible = true }, // 删除 del(index) { let params = { id: this.books[index].id } delBook(params).then((res) => { console.log(res) this.get() }) }, }, created() { this.get() } } </script> <style scoped> table tr td { width: 150px; border: solid 1px black; } </style>
-
- src\components\BookEdit.vue 子组件
<template>
<div>
<el-dialog
title="新增图书"
:visible="visible"
>
<div><span>图书名称:</span>
<el-input
class='elinput'
v-model="data.btitle"
></el-input>
</div>
<div><span>发布日期:</span>
<el-input
class='elinput'
v-model="data.bpub_date"
>
</el-input>
</div>
<div><span>阅读量:</span>
<el-input
class='elinput'
v-model="data.bread"
></el-input>
</div>
<div><span>评论量:</span>
<el-input
class='elinput'
v-model="data.bcomment"
></el-input>
</div>
<el-button @click="cancel">取 消</el-button>
<el-button
type="primary"
@click="addBook"
>确 定
</el-button>
</el-dialog>
</div>
</template>
<script>
// import { addbook } from '@/http/apis'
export default {
props: ['data', 'visible'],
data() {
return {}
},
methods: {
addBook() {
this.$emit('update:visible', false)
this.$emit('save')
},
cancel() {
this.$emit('update:visible', false)
}
},
mounted() {
}
}
</script>
<style scoped>
.elinput {
width: 220px;
height: 40px;
}
</style>
-
src/mian.js 引入ElementUI
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false // 使用 elementui // npm i element-ui -S 安装到当前项目 import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) /* eslint-disable no-new */ new Vue({ el: '#app', router, components: {App}, template: '<App/>' }) Vue.config.productionTip = false // 使用 elementui // npm i element-ui -S 安装到当前项目 import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) /* eslint-disable no-new */ new Vue({ el: '#app', router, components: {App}, template: '<App/>' })
展示