zoukankan      html  css  js  c++  java
  • 图书系统哦

    3.2 settings.py

    • 外加跨域
    """
    Django settings for django01 project.
    
    Generated by 'django-admin startproject' using Django 2.2.
    
    For more information on this file, see
    https://docs.djangoproject.com/en/2.2/topics/settings/
    
    For the full list of settings and their values, see
    https://docs.djangoproject.com/en/2.2/ref/settings/
    """
    
    import os
    
    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
    
    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = 'c(9!f^)7+fa%p0@-w_cj(d)7(d_1ku5me9v*c8kjhod((8u&zq'
    
    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = True
    
    ALLOWED_HOSTS = ['*']
    
    
    # Application definition
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'corsheaders',
        # 跨域第一步
        'rest_framework',
        'apps.app01',
        # app配置
    ]
    
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        # 'django.middleware.csrf.CsrfViewMiddleware',
        # 不注释会产生问题
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware'
    ]
    
    ROOT_URLCONF = 'django01.urls'
    
    CORS_ORIGIN_WHITELIST = (
        'http://127.0.0.1:8080',
        'http://localhost:8080',
    )
    
    CORS_ALLOW_CREDENTIALS = True	# 允许携带cookie
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            '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',
                ],
            },
        },
    ]
    
    WSGI_APPLICATION = 'django01.wsgi.application'
    
    
    # Database
    # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'booksdb',
            'USER': 'root',
            'PASSWORD': '1',
            'HOST': '127.0.0.1',
            'PORT': 3306
        }
    }
    
    
    # Password validation
    # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
    
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]
    
    
    # Internationalization
    # https://docs.djangoproject.com/en/2.2/topics/i18n/
    
    LANGUAGE_CODE = 'zh-hans'
    
    TIME_ZONE = 'Asia/Shanghai'
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = False
    
    
    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/2.2/howto/static-files/
    
    STATIC_URL = '/static/'
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
    

    3.3 主路由urls.py

    """django01 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.conf import settings
    from django.conf.urls.static import static
    from django.contrib import admin
    from django.urls import path, include, re_path
    from django.views.static import serve
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('app01/', include('apps.app01.urls')),
        re_path("^(?P<path>.*)/$", serve, {'document_root': settings.MEDIA_ROOT})
    # 正则路由, <path>匹配任意除了换行
    
    ]
    
    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
    
    # http://127.0.0.1:8000/media/img/xxxx.jpg
    

    3.4 子路由urls.py

    # -*- coding: utf-8 -*-
    from django.urls import path
    from . import views
    urlpatterns = [
        path('books/', views.BookView.as_view()),       # 图书增删改查
    ]
    

    3.5 models.py

    from django.db import models
    
    # Create your models here.
    class Books(models.Model):
        books_name = models.CharField(max_length=20)
        public_time = models.DateField()
        read = models.IntegerField()
        comment = models.IntegerField()
        is_delete = models.BooleanField(default=False)
    
        class Meta:
            db_table = 'books'
    

    3.6 django01/__init__.py

    import pymysql
    pymysql.install_as_MySQLdb()
    

    3.7 serializer.py

    # -*- coding: utf-8 -*-
    from rest_framework import serializers
    from .models import Books
    
    class BooksSerializer(serializers.ModelSerializer):
        class Meta:
            model = Books
            fields = '__all__'
    

    3.8 views.py

    import json
    
    from django.shortcuts import render
    
    # Create your views here.
    from rest_framework.response import Response
    from rest_framework.views import APIView
    
    from .models import *
    from .serializer import BooksSerializer
    # 导包一定要有 .
    
    
    class BookView(APIView):
        def get(self, request):
            queryset = Books.objects.filter(is_delete=False)
            books_serializer = BooksSerializer(queryset, many=True)
            return Response({
                'books':books_serializer.data,
                'code':200
            })
            # book_list = queryset.values('books_name', 'public_time', 'read', 'comment')
            # return Response(book_list)
    
        def post(self, request):
            body_json = request.body.decode()
            body_dict = json.loads(body_json)
            Books.objects.create(**body_dict)
            return Response(
                {'msg':'添加成功', 'code':200}
            )
        def put(self, request):
            body_json = request.body.decode()
            body_dict = json.loads(body_json)
            id = body_dict.get('id')
            '''
                books_name = models.CharField(max_length=20)
                public_time = models.DateField()
                read = models.IntegerField()
                comment = models.IntegerField()
                is_delete = models.BooleanField(default=False)
            '''
            book = Books.objects.filter(id=id).first()
            book.books_name = body_dict.get('books_name')
            book.public_time = body_dict.get('public_time')
            book.read = body_dict.get('read')
            book.comment = body_dict.get('comment')
            book.save()
            return Response(
                {'msg':'修改成功', 'code':200}
            )
    
        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 Response(
                {'msg':'删除成功', 'code':200}
            )
    

    4 Vue端

    4.1 总目录概览

    image-20201029210431576

    详解:
    src(项目代码主要在这里)*自己创建
    assets 图片等资源
    components 公用组件(在很多.vue文件中都会引用)
    http 封装axios请求*
    view 除了公共组件,所有的.vue文件都写入*
    main.js 项目运行入口(引入js组件,可以在任何.vue文件中使用)
    index.html 是主页面(所有页面都嵌入,有一个index-router路由)导入css、js文件,在任何一个.vue文件中直接使用
    

    4.2 http文件夹下(跨域)

    4.2.1 http/index.js
    // 阔落给的(适用)
    // import axios from 'axios'
    // axios.defaults.baseURL="http://192.168.56.100:8000/"
    // axios.defaults.timeout = 1000000;
    // axios.defaults.headers.post['Content-Type'] = 'application/json';
    // axios.defaults.headers.put['Content-Type'] = 'application/json';
    
    // axios.interceptors.request.use(    
    //     config => {
    //         // 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
    //         const token = sessionStorage.getItem("jwt_token")   
    //         console.log(token)  
    //         if (token){
    //             config.headers.Authorization = 'JWT '+ token
    //         }           
    //         return config;    
    //     },    
    //     error => {        
    //         return Promise.error(error);    
    //     })
    
    
    
    // axios.interceptors.response.use(    
    //     // 请求成功
    //     res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),    
    
    //     // 请求失败
    //     error => {
    //         if (error.response) {
    //             // 判断一下返回结果的status == 401?  ==401跳转登录页面。  !=401passs
    //             console.log(error.response)
    //             if(error.response.status===401){
    //                 // 跳转不可以使用this.$router.push方法、
    //                 // this.$router.push({path:'/login'})
    //                 window.location.href="http://127.0.0.1:8080/#/login"
    //             }else{
    //                 // errorHandle(response.status, response.data.message);
    //                 return Promise.reject(error.response);
    //             }
    //             // 请求已发出,但是不在2xx的范围 
    //         } else {
    //             // 处理断网的情况
    //             // eg:请求超时或断网时,更新state的network状态
    //             // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
    //             // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
    //             // store.commit('changeNetwork', false);
    //             return Promise.reject(error.response);
    //         }
    //     });
    
    
    // // 封装xiaos请求  封装axios里的get
    // export function axios_get(url,params){
    //     return new Promise(
    //         (resolve,reject)=>{
    //             axios.get(url,{params:params})
    //             .then(res=>{
    //                 console.log("封装信息的的res",res)
    //                 resolve(res.data)
    //             }).catch(err=>{
    //                 reject(err.data)
    //             })
    //         }
    //     )
    // }
    
    
    // export function axios_post(url,data){
    //     return new Promise(
    //         (resolve,reject)=>{
    //             console.log(data)
    //             axios.post(url,JSON.stringify(data))
    //             .then(res=>{
    //                 console.log("封装信息的的res",res)
    //                 resolve(res.data)
    //             }).catch(err=>{
    //                 reject(err.data)
    //             })
    //         }
    //     )
    // }
    
    // export function axios_put(url,data){
    //     return new Promise(
    //         (resolve,reject)=>{
    //             console.log(data)
    //             axios.put(url,JSON.stringify(data))
    //             .then(res=>{
    //                 console.log("封装信息的的res",res)
    //                 resolve(res.data)
    //             }).catch(err=>{
    //                 reject(err.data)
    //             })
    //         }
    //     )
    // }
    
    // export function axios_delete(url,data){
    //     return new Promise(
    //         (resolve,reject)=>{
    //             console.log(data)
    //             axios.delete(url,{params:data})
    //             .then(res=>{
    //                 console.log("封装信息的的res",res)
    //                 resolve(res.data)
    //             }).catch(err=>{
    //                 reject(err.data)
    //             })
    //         }
    //     )
    // }
    
    // -------------------------------------------------------------------------------------------------
    
    // 老师上课讲的
    /* eslint-disable */
    // 第一步:实例化axios对象,简单封装
    const axios = require('axios');                         // 生成一个axios实例
    axios.defaults.baseURL = 'http://192.168.56.100:8000';  // 设置请求后端的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) => {
            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;
    
    4.2.2 http/apis.js
    /* eslint-disable */
    // 接口信息,生成请求方法
    // 引入get方法,post方法
    
    // import {axios_get,axios_post,axios_delete,axios_put} from '../http/index'  
    
    // export const getBookList = p  => axios_get("/app01/books/",p)  
    
    
    /* eslint-disable */
    import { get, post, put, del } from './index'
    
    export const getBookList = (params, headers) => get("/app01/books/", params, headers)
    export const addBook = (params, headers) => post("/app01/books/", params, headers) 
    export const editBook = (params, headers) => put("/app01/books/", params, headers) 
    export const delBook = (params, headers) => del("/app01/books/", params, headers)
    

    4.3 组件

    4.3.1 组件总思路

    image-20201029211706541

    4.3.2 components/BookEdit.vue
    <template>
        <div>
            <el-dialog title="新增图书" :visible="visible" > 
                <div>
                    <span>图书名称:</span> 
                    <el-input class='elinput' v-model="data.books_name" ></el-input> 
                </div> 
                <div>
                    <span>发布日期:</span> 
                    <el-input class='elinput' v-model="data.public_time" ></el-input> 
                </div> 
                <div>
                    <span>阅读量:</span> 
                    <el-input class='elinput' v-model="data.read" ></el-input> 
                </div> 
                <div>
                    <span>评论量:</span> 
                    <el-input class='elinput' v-model="data.comment" ></el-input> 
                </div> 
                <el-button @click="cancel">取 消</el-button> 
                <el-button type="primary" @click="addBook" >确 定</el-button> 
            </el-dialog>
        </div>
    </template>
    
    <script>
    export default {
        props: ['data', 'visible'],
        data() {
            return {
    
            }
        },
        methods: {
            addBook(){
                this.$emit('update:visible', false)
                this.$emit('save')
            },
            cancel(){
                this.$emit('update:visible', false)
            }
        },
        created() {
    
        }
    }
    </script>
    
    <style scoped>
    .elinput { 
         220px; 
        height: 40px; 
    }
    </style>
    

    4.4 主页面

    4.4.1 viewsooksBooks.vue
    <template>
        <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:0 auto">
                    <tr>
                        <th>图书编号</th>
                        <th>图书名字</th>
                        <th>出版时间</th>
                        <th>阅读数</th>
                        <th>评论数</th>
                        <th>操作</th>
                    </tr>
                    <tr v-for="(book, index) in books_list" :key="index">
                        <td>{{book.id}}</td>                    
                        <td>{{book.books_name}}</td>
                        <td>{{book.public_time}}</td>
                        <td>{{book.read}}</td>
                        <td>{{book.comment}}</td>
                        <td>
                            <button @click="edit(index)">修改</button>
                            <button @click="del(index)">删除</button>
                        </td>
                    </tr>
                </table>
            </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_list:[],
                editData: { 
                    // 编辑的内容 
                    books_name: "", 
                    public_time: "", 
                    read: 100, 
                    comment: 0
                }
            }
        },
        methods: {
            // 1.点击新增图书时初始化数据 
            addNew() { 
                this.editData = { 
                    // 初始化 编辑内容 
                    books_name: "", 
                    public_time: "", 
                    read: '', 
                    comment: '' 
                }
                this.dialogVisible = true
                 // 显示弹框 
            },
            // 2.获取图书列表,获取数据
            get(){
                getBookList().then((data) =>{
                    this.books_list = data.books
                    console.log(this.books_list)
                })
            },
            // 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_list[index])) 
                    // 复制 this.books_list[index] 的数据
                    // this.editData = this.books_list[index] 
                    this.dialogVisible = true 
                },
            // 删除 
            del(index) { 
                let params = { 
                    id: this.books_list[index].id 
                }
                delBook(params).then(res=>{ 
                    console.log(res) 
                    this.get() 
                    }) 
            }
        },
        created() {
            this.get()
        }
    }
    </script>
    
    <style scoped>
    
    </style>
    
    4.4.2 修饰符问题
    vue修饰符sync的功能是:当一个子组件改变了一个prop的值时,这个变化也会同步到父组件中所绑定。如果我们不用.sync,我们想做上面的那个弹窗功能,我们也可以props传初始值,然后事件监听,实现起来也不算复杂。
    

  • 相关阅读:
    [bzoj2333] [SCOI2011]棘手的操作 (可并堆)
    自定义控件1_切换按钮
    View Animation 视图动画全解
    从图库中选取图片设置给ImageView
    一张图认识安卓shape属性
    自定义Dialog(QQ头像选择弹出的对话框)
    Toolbar和menu使用
    LIB和DLL的区别与使用
    C++调用webservice
    夯实Java基础系列5:Java文件和Java包结构
  • 原文地址:https://www.cnblogs.com/msdreamer/p/13909080.html
Copyright © 2011-2022 走看看