1. 程式人生 > 實用技巧 >圖書管理系統(modelviewset)前後端調聯

圖書管理系統(modelviewset)前後端調聯

使用view Djang介面

  1. books/view

    1. 註冊

    2. INSTALLED_APPS = [
          'books.apps.BooksConfig',
      
          'corsheaders',
          'rest_framework',
          'django_filters',
      
      ]
      
    3. 配置跨域

    4. #1.新增cors  登出csrf
      MIDDLEWARE = [
          'django.middleware.security.SecurityMiddleware',
          'django.contrib.sessions.middleware.SessionMiddleware',
          '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',
      ]
      
      
      #2.新增
      CORS_ALLOW_CREDENTIALS = True
      CORS_ORIGIN_ALLOW_ALL = True
      CORS_ORIGIN_WHITELIST = (
          'http://127.0.0.1:8080',
          'http://localhost:8080',
      )
      
  2. books/models

    1. from django.db import models
      
      
      # Create your models here.
      
      class Book(models.Model):
          name = models.CharField(max_length=32)
          price = models.IntegerField()
          datatime = models.DateTimeField(auto_now=True)
          browse = models.IntegerField(default=0)
      
          class Meta:
              db_table = "圖書"
      
  3. books/serializers

    1. """
      author:翔翔
      date:
      use:
      """
      from rest_framework import serializers
      from .models import *
      
      
      class BookSerializer(serializers.Serializer):
          id = serializers.CharField(read_only=True)
          name = serializers.CharField()
          price = serializers.IntegerField()
          browse = serializers.IntegerField()
          datatime = serializers.DateTimeField()
      
          class Meta:
              model = Book
      
      
      class BooksModelSerializer(serializers.ModelSerializer):
          class Meta:
              model = Book
              fields = "__all__"
      
  4. 遷移資料庫

    1. python  manage.py makemigrations
      python manage.py  migrate
      
  5. books/views(使用View)

    1. """
      author:翔翔
      date:
      use:
      """
      import json
      
      from django.http import JsonResponse, HttpResponse
      from django.shortcuts import render
      from django.views import View
      from rest_framework.response import Response
      from rest_framework.views import APIView
      from .serializers import *
      from .models import *
      from rest_framework.viewsets import ModelViewSet
      from rest_framework.permissions import AllowAny, IsAdminUser, IsAuthenticated, IsAuthenticatedOrReadOnly, BasePermission
      
      
      class BooksModelViewSet(ModelViewSet):
          permission_classes = [AllowAny, ]   #自定義許可權
       
          queryset = Book.objects.all()
          serializer_class = BooksModelSerializer
      
      
  6. books/urls

    1. from django.urls import path
      from rest_framework.routers import DefaultRouter
      from .views2 import *
      
      router = DefaultRouter()
      router.register(r'book1', BooksModelViewSet)  # modelviewset 介面  增刪改查
      urlpatterns = [
      ]
      
      urlpatterns += router.urls
      
      

Vue頁面

  1. 下載[email protected] 下載element-ui

    1. cnpm install --save [email protected]

    2. cnpm install --save element-ui

      1. src/main.js引用全域性

      2. //element
        import ElementUI from 'element-ui'
        import 'element-ui/lib/theme-chalk/index.css'
        Vue.use(ElementUI)
        
  2. 配置跨域

    1. 在http/index.js

    2. import axios from 'axios'
      // axios.defaults.baseURL = "http://127.0.0.1:8000/"
      axios.defaults.baseURL = "http://192.168.56.100:8888/"
      
      
      //全域性設定網路超時
      axios.defaults.timeout = 10000;
      
      //設定請求頭資訊
      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 = localStorage.getItem("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/"
            } 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請求
      
      // 封裝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)
            })
          }
        )
      }
      
      // 封裝post請求
      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)
            })
          }
        )
      }
      
      // 封裝put請求
      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)
            })
          }
        )
      }
      
      // 封裝delete請求
      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)
            })
          }
        )
      }
      
    3. 在http/apis.js

    4. /* eslint-disable */
      
      import {axios_get, axios_post, axios_delete, axios_put} from './index.js'
      
      export const getBooks = (params, headers) => axios_get("/books/book1/", params, headers)
      export const AddBooks = (params, headers) => axios_post("/books/book1/", params, headers)
      export const UpBooks = (params, headers) => axios_put("/books/book1/" + params.id + '/', params, headers)
      export const DelBooks = (params, headers) => axios_delete("/books/book1/" + params.id + '/', params, headers)
      
      
  3. views/book-manage/books.vue

    1. <template>
      
        <div>
          <el-button type="primary" @click="add">上傳圖書<i class="el-icon-upload el-icon--right"></i></el-button>
          <el-button type="primary" @click="open">上傳圖書<i class="el-icon-upload el-icon--right"></i></el-button>
          <el-table
            :data="tableData"
            style="width: 100%">
            <el-table-column
              label="日期"
              width="300">
              <template slot-scope="scope">
                <i class="el-icon-time"></i>
                <span style="margin-left: 10px">{{ scope.row.datatime }}</span>
              </template>
            </el-table-column>
            <el-table-column
              label="書名"
              width="180">
              <template slot-scope="scope">
                <el-popover trigger="hover" placement="top">
                  <p>書名: {{ scope.row.browse }}</p>
                  <div slot="reference" class="name-wrapper">
                    <el-tag size="medium">{{ scope.row.name }}</el-tag>
                  </div>
                </el-popover>
              </template>
            </el-table-column>
            <el-table-column
              label="價格"
              width="180">
              <template slot-scope="scope">
                <el-popover trigger="hover" placement="top">
                  <p>書名: {{ scope.row.price }}</p>
                  <div slot="reference" class="name-wrapper">
                    <el-tag size="medium">{{ scope.row.price }}</el-tag>
                  </div>
                </el-popover>
              </template>
            </el-table-column>
            <el-table-column
              label="瀏覽數"
              width="180">
              <template slot-scope="scope">
                <el-popover trigger="hover" placement="top">
                  <p>書名: {{ scope.row.name }}</p>
                  <div slot="reference" class="name-wrapper">
                    <el-tag size="medium">{{ scope.row.browse }}</el-tag>
                  </div>
                </el-popover>
              </template>
            </el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button
                  size="mini"
                  @click="handleEdit(scope.row.id,scope.row)"
                >編輯
                </el-button>
                <el-button
                  size="mini"
                  type="danger"
                  @click="handleDelete(scope.row.id)">刪除
                </el-button>
              </template>
            </el-table-column>
          </el-table>
          <BookEdit
            :visible.sync='dialogVisible'
            :data="editData"
            @book="book"
          ></BookEdit>
        </div>
      
      </template>
      
      <script>
      import {AddBooks, DelBooks, getBookList, getBooks, UpBooks} from "../../http/apis";
      import BookEdit from "./components/BookEdit";
      
      export default {
        name: "Books",
        components: {
          BookEdit,
      
        },
        data() {
          return {
            dialogVisible: false,
            tableData: [],
            editData: {  // 編輯的內容
              name: "",
              datetime: "",
              price: 0,
              browse: 0
            }
          }
        },
        methods: {
          show() {
            getBooks().then(res => {
              console.log(res)
              this.tableData = res.results
      
            })
          },
          handleEdit(pk, books_list) {
            this.editData = books_list
            this.dialogVisible = true
            console.log(books_list)
          },
          handleDelete(pk) {
            DelBooks({id: pk}).then(res => {
              console.log(res)
              this.show()
            }).catch(err => {
              this.show()
      
            })
          },
          add() {
            this.dialogVisible = true
          },
      
          book() {
            if (this.editData.id) {
              let params = {id: this.editData.id}
              console.log(params)
              UpBooks(this.editData).then(res => {
                console.log(res)
                this.show()
              })
            } else {
              AddBooks(this.editData).then(res => {
                console.log(res)
                this.show()
              }).catch(err => {
                this.show()
              })
            }
          },
          open() {
            this.$prompt('請輸入郵箱', '提示', {
              confirmButtonText: '確定',
              cancelButtonText: '取消',
            }).then(({ value }) => {
              this.$message({
                type: 'success',
                message: '你的郵箱是: ' + value
              });
            }).catch(() => {
              this.$message({
                type: 'info',
                message: '取消輸入'
              });
            });
          }
      
      
        },
      //鉤子方法
        mounted() {
          console.log('這是初始化方法');
        }
        ,
        created() {
          this.show()
        }
        ,
      //監聽屬性
        watch: {}
        ,
      //計算屬性
        computed: {}
      }
      </script>
      
      <style scoped>
      
      </style>
      
      
  4. views/book-manage/components/BookEdit

    1. <template>
        <div>
          <div>
            <el-dialog
              :visible="visible"
            >
              <el-radio-group v-model="labelPosition" size="small">
                <el-radio-button label="left">左對齊</el-radio-button>
                <el-radio-button label="right">右對齊</el-radio-button>
                <el-radio-button label="top">頂部對齊</el-radio-button>
              </el-radio-group>
              <div style="margin: 20px;"></div>
              <!--        <el-form :label-position="labelPosition" label-width="80px" :model="data">-->
              <el-form :label-position="labelPosition" label-width="80px">
                <el-form-item label="書名">
                  <el-input v-model="data.name"></el-input>
                </el-form-item>
                <el-form-item label="價格">
                  <el-input v-model="data.price"></el-input>
                </el-form-item>
                <el-form-item label="瀏覽數">
                  <el-input v-model="data.browse"></el-input>
                </el-form-item>
              </el-form>
              <el-button type="danger" round @click="cancel">取 消</el-button>
              <el-button type="success" round @click="book">提交</el-button>
            </el-dialog>
          </div>
      
        </div>
      
      </template>
      
      <script>
      export default {
        name: "BookEdit",
        props: ['data', 'visible'],
        data() {
          return {
            labelPosition: 'right',
            // formLabelAlign: {
            //   name: '',
            //   region: '',
            //   type: ''
            // }
          }
        },
        methods: {
          cancel() {
            //$emit(update: prop, "newPropVulue")  這個模式,使子元件向父元件傳達:更新屬性,並丟擲新的屬性值
            this.$emit('update:visible', false)
          },
          book() {
            this.$emit('update:visible', false)
            this.$emit('book')
          },
        },
      
      
        //鉤子方法
        mounted() {
          console.log('這是初始化方法');
        },
        created() {
      
        },
        //監聽屬性
        watch: {},
        //計算屬性
        computed: {}
      }
      </script>
      
      <style scoped>
      
      </style>