Python Web 前后端分离 背景管理系统 Django+vue(完备代码) ...

打印 上一主题 下一主题

主题 884|帖子 884|积分 2652

1.前后端分离的架构

在前后端分离的架构中,前端和后端分别作为独立的项目举行开辟和摆设。前端项目通过API与后端项目举行通信。


  • 前端:使用Vue.js构建用户界面,调用后端提供的RESTful API获取和发送数据。
  • 后端:使用Django构建API,处理业务逻辑和数据存储
2.创建django项目及vue项目

创建app的时候必要进入项目的目录下  win10 cd xmmc
  1. django-admin startproject xmmc
  2. django-admin startapp app01
复制代码
以管理员身份打开命令行界面,进入恣意一个想要创建项目的文件夹
  1. vue create vueproject
复制代码
然后按自己的需求选择,可以去专门搜一下创建vue的教程
3.设置setting

(1)设置数据库

  1. DATABASES = {
  2.     'default': {
  3.         'ENGINE': 'django.db.backends.mysql',  # 加载mysql引擎
  4.         'NAME': 'db_goods',  # 数据库名称
  5.         'USER': 'root',  # mysql账户名
  6.         'PASSWORD': '123456',  # mysql账户密码
  7.         'PORT': 3306,  # 端口号
  8.         'HOST': 'localhost'
  9.     }
  10. }
复制代码
(2)设置模板文件

  1. TEMPLATES = [
  2.     {
  3.         'BACKEND': 'django.template.backends.django.DjangoTemplates',
  4.         'DIRS': [os.path.join(BASE_DIR, 'templates')],
  5.         'APP_DIRS': True,
  6.         'OPTIONS': {
  7.             'context_processors': [
  8.                 'django.template.context_processors.debug',
  9.                 'django.template.context_processors.request',
  10.                 'django.contrib.auth.context_processors.auth',
  11.                 'django.contrib.messages.context_processors.messages',
  12.             ],
  13.         },
  14.     },
  15. ]
复制代码
(3)设置静态文件

  1. STATIC_URL = 'static/'
  2. STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
复制代码
(4)注册app(使用创建 django-admin startapp app名称)


(5)解决跨域问题


  1. MIDDLEWARE = [
  2.     'django.middleware.security.SecurityMiddleware',
  3.     'django.contrib.sessions.middleware.SessionMiddleware',
  4.     'corsheaders.middleware.CorsMiddleware',  # 跨域,一定要写在第三行
  5.     'django.middleware.common.CommonMiddleware',
  6.     # 'django.middleware.csrf.CsrfViewMiddleware',
  7.     'django.contrib.auth.middleware.AuthenticationMiddleware',
  8.     'django.contrib.messages.middleware.MessageMiddleware',
  9.     'django.middleware.clickjacking.XFrameOptionsMiddleware',
  10. ]
复制代码
  1. CORS_ORIGIN_ALLOW_ALL = True
  2. CORS_ALLOW_CREDENTIALS = True
  3. # 允许所有的请求头
  4. CORS_ALLOW_HEADERS = ('*')
复制代码
4.查看目录结构

  1. web_django/
  2. ├── static/
  3. ├── templates/
  4. ├── user/
  5. │   ├── migrations/
  6. │   ├── __init__.py
  7. │   ├── admin.py
  8. │   ├── apps.py
  9. │   ├── models.py
  10. │   ├── tests.py
  11. │   ├── urls.py
  12. │   ├── views.py
  13. ├── web_django/
  14. │   ├── __init__.py
  15. │   ├── asgi.py
  16. │   ├── settings.py
  17. │   ├── urls.py
  18. │   ├── wsgi.py
  19. ├── webapp/
  20. │   ├── migrations/
  21. │   ├── views/
  22. │   ├── __init__.py
  23. │   ├── admin.py
  24. │   ├── apps.py
  25. │   ├── models.py
  26. │   ├── tests.py
  27. │   ├── urls.py
  28. │   ├── views.py
复制代码
5.前后端实现登录

(1)编写登录的前端(完备代码)

  1. <template>
  2.   <div class="login-background">
  3.     <div class="login-container">
  4.       <el-card class="box-card" style="opacity: 0.9;">
  5.         <h2>登录</h2>
  6.         <el-form
  7.           :model="ruleForm"
  8.           status-icon
  9.           :rules="rules"
  10.           ref="ruleForm"
  11.           label-position="left"
  12.           label-width="70px"
  13.           class="login-form"
  14.         >
  15.           <el-form-item label="用户名" prop="uname">
  16.             <el-input v-model="ruleForm.uname"></el-input>
  17.           </el-form-item>
  18.           <el-form-item label="密码" prop="password">
  19.             <el-input
  20.               type="password"
  21.               v-model="ruleForm.password"
  22.               autocomplete="off"
  23.             ></el-input>
  24.           </el-form-item>
  25.         </el-form>
  26.         <div class="btn-group">
  27.           <el-button type="primary" @click="submitForm('ruleForm')"
  28.             >登录</el-button
  29.           >
  30.           <el-button @click="resetForm('ruleForm')">重置</el-button>
  31.           <router-link to="/register">
  32.             <el-button style="margin-left:10px">注册</el-button>
  33.           </router-link>
  34.         </div>
  35.       </el-card>
  36.     </div>
  37.   </div>
  38. </template>
  39. <script>
  40. import axios from 'axios';
  41. export default {
  42.   data() {
  43.     return {
  44.       ruleForm: {
  45.         uname: "",
  46.         password: "",
  47.       },
  48.       rules: {
  49.         uname: [
  50.           { required: true, message: "用户名不能为空!", trigger: "blur" },
  51.         ],
  52.         password: [
  53.           { required: true, message: "密码不能为空!", trigger: "blur" },
  54.         ],
  55.       },
  56.     };
  57.   },
  58.   methods: {
  59.     async submitForm(formName) {
  60.       try {
  61.         const response = await axios.post('http://127.0.0.1:8005/user/login/', this.ruleForm);
  62.         // 在这里处理后端响应
  63.         console.log(response.data);
  64.         if (response.data.success) {
  65.           sessionStorage.setItem('username', JSON.stringify(response.data))
  66.           // 登录成功,跳转到 Index 页面
  67.           this.$router.push('/components/News');
  68.         } else {
  69.           // 登录失败,显示错误消息或其他处理
  70.           console.error('登录失败:', response.data.message);
  71.         }
  72.       } catch (error) {
  73.         console.error('提交表单时发生错误:', error);
  74.       }
  75.     },
  76.     resetForm(formName) {
  77.       this.$refs[formName].resetFields();
  78.     },
  79.   },
  80. };
  81. </script>
  82. <style scoped>
  83. .login-background {
  84.   background-image: url('https://pic4.zhimg.com/v2-b730c73ebd78bd5f22293aab0d343f4b_r.jpg?source=1940ef5c');
  85.   background-size: cover;
  86.   background-position: center;
  87.   height: 100vh;
  88.   display: flex;
  89.   justify-content: center;
  90.   align-items: center;
  91. }
  92. .box-card {
  93.   width: 400px;
  94. }
  95. .login-form {
  96.   margin: auto;
  97. }
  98. .btn-group {
  99.   margin-top: 20px;
  100. }
  101. </style>
复制代码
登录效果图
(2)编写登录后端views(视图文件)


  1. from django.http import JsonResponse
  2. from django.contrib.auth import authenticate, login
  3. from django.contrib.auth.models import User
  4. import json
  5. def login_view(request):
  6.     # if request.method == 'GET':
  7.     if request.method == 'POST':
  8.         js = request.body.decode('utf8')
  9.         data = json.loads(js)
  10.         username = data['uname']
  11.         password = data['password']
  12.         # 使用 Django 自带的 authenticate 方法验证用户身份
  13.         user = authenticate(request, username=username, password=password)
  14.         if user is not None:
  15.             # 登录成功,将用户添加到当前会话中
  16.             login(request, user)
  17.             print(user)
  18.             return JsonResponse({'code': 200, 'success': True, 'message': '登录成功', 'username': str(user)})
  19.         else:
  20.             # 登录失败,返回错误消息
  21.             return JsonResponse({'code': 500, 'success': False, 'message': '用户名或密码错误', })
  22.     # 如果不是 POST 请求,则返回错误消息
  23.     return JsonResponse({'success': False, 'message': '只支持 POST 请求'})
  24. def register_view(request):
  25.     if request.method == 'POST':
  26.         # 从请求体中获取JSON数据
  27.         js = request.body.decode('utf8')
  28.         data = json.loads(js)
  29.         print(data)
  30.         username = data['uname']
  31.         password = data['password']
  32.         # 检查用户名是否已经存在
  33.         if User.objects.filter(username=username).exists():
  34.             return JsonResponse({'code': 400, 'success': False, 'message': '用户名已存在'})
  35.         # 创建用户
  36.         user = User.objects.create_user(username=username, password=password)
  37.         # 返回成功消息
  38.         return JsonResponse({'code': 200, 'success': True, 'message': '注册成功', 'username': username})
  39.     # 如果不是 POST 请求,则返回错误消息
  40.     return JsonResponse({'code': 405, 'success': False, 'message': '只支持 POST 请求'})
复制代码
(3)子视图文件(在user app中创建一个urls)

  1. from . import views
  2. from django.urls import path, re_path
  3. urlpatterns = [
  4.     path('login/', views.login_view, name='login'),
  5.     path('register/', views.register_view, name='register'),
  6. ]
复制代码
(4)在主路由中设置user app(主路由跟setting在同一个文件夹)


6.管理页面的前后端完备代码 

(1)管理页面前端代码(业务范围页面)

  1. <template>
  2.   <div>
  3.     <el-row style="height: 50px;">
  4.       <el-col :span="1" class="grid">
  5.         <el-button
  6.           type="success"
  7.           @click="showAddDialog"
  8.           icon="el-icon-circle-plus-outline"
  9.           size="mini"
  10.           round
  11.         >新增</el-button>
  12.       </el-col>
  13.     </el-row>
  14.     <el-dialog title="新增" :visible.sync="addDialogVisible" width="42%">
  15.       <el-form :model="addFormData" :rules="addFormRules" ref="addForm" label-width="120px">
  16.         <el-form-item label="标题" prop="title">
  17.           <el-input v-model="addFormData.title"></el-input>
  18.         </el-form-item>
  19.         <el-form-item label="图片链接" prop="image_url">
  20.           <el-input v-model="addFormData.image_url"></el-input>
  21.         </el-form-item>
  22.         <el-form-item label="内容" prop="content">
  23.           <el-input v-model="addFormData.content"></el-input>
  24.         </el-form-item>
  25.         <el-form-item label="图片详情链接" prop="details_image_url">
  26.           <el-input v-model="addFormData.details_image_url"></el-input>
  27.         </el-form-item>
  28.       </el-form>
  29.       <span slot="footer" class="dialog-footer">
  30.         <el-button @click="addDialogVisible = false">取 消</el-button>
  31.         <el-button type="primary" @click="submitAddForm">确 定</el-button>
  32.       </span>
  33.     </el-dialog>
  34.     <el-dialog title="编辑" :visible.sync="editDialogVisible" width="40%">
  35.       <el-form :model="editFormData" :rules="editFormRules" ref="editForm" label-width="100px">
  36.         <el-form-item label="标题" prop="title">
  37.           <el-input v-model="editFormData.title"></el-input>
  38.         </el-form-item>
  39.         <el-form-item label="图片链接" prop="image_url">
  40.           <el-input v-model="editFormData.image_url"></el-input>
  41.         </el-form-item>
  42.         <el-form-item label="内容" prop="content">
  43.           <el-input v-model="editFormData.content"></el-input>
  44.         </el-form-item>
  45.         <el-form-item label="图片详情链接" prop="details_image_url">
  46.           <el-input v-model="editFormData.details_image_url"></el-input>
  47.         </el-form-item>
  48.       </el-form>
  49.       <span slot="footer" class="dialog-footer">
  50.         <el-button @click="editDialogVisible = false">取 消</el-button>
  51.         <el-button type="primary" @click="submitEditForm">确 定</el-button>
  52.       </span>
  53.     </el-dialog>
  54.     <el-table
  55.       :data="tableData.slice((currentPage-1)*pagesize,currentPage*pagesize)"
  56.       style="width: 100%; margin-top: 10px;"
  57.       border
  58.       stripe
  59.       ref="multipleTable"
  60.       tooltip-effect="dark"
  61.     >
  62.       <el-table-column label="序号" type="index" width="80px" align="center"></el-table-column>
  63.       <el-table-column prop="title" width="100px" label="标题"></el-table-column>
  64.       <el-table-column prop="image_url" width="150px" label="图片链接"></el-table-column>
  65.       <el-table-column prop="content" width="120px" label="内容"></el-table-column>
  66.       <el-table-column prop="details_image_url" label="图片详情链接"></el-table-column>
  67.       <el-table-column width="190px" label="操作">
  68.         <template slot-scope="scope">
  69.           <el-button type="primary" icon="el-icon-edit" size="mini" @click="editBook(scope.row)">编辑</el-button>
  70.           <el-button
  71.             icon="el-icon-delete"
  72.             size="mini"
  73.             type="danger"
  74.             @click="confirmDelete(scope.row)"
  75.           >删除</el-button>
  76.         </template>
  77.       </el-table-column>
  78.     </el-table>
  79.     <div class="pagination">
  80.       <el-pagination
  81.         @size-change="handleSizeChange"
  82.         @current-change="handleCurrentChange"
  83.         :current-page="currentPage"
  84.         :page-sizes="[5, 10, 20, 40]"
  85.         :page-size="pagesize"
  86.         layout="total, sizes,prev, pager, next"
  87.         :total="tableData.length"
  88.         prev-text="上一页"
  89.         next-text="下一页"
  90.       ></el-pagination>
  91.     </div>
  92.   </div>
  93. </template>
  94. <script>
  95. import axios from "axios";
  96. import { MessageBox } from "element-ui";
  97. export default {
  98.   name: "app",
  99.   data() {
  100.     return {
  101.       currentPage: 1, // 默认显示页面为1
  102.       pagesize: 5, // 每页的数据条数
  103.       tableData: [], // 需要 data 定义一些,tableData 定义一个空数组,请求的数据都是存放这里面
  104.       addDialogVisible: false,
  105.       activeIndex2: "1",
  106.       addFormData: {
  107.         title: "",
  108.         image_url: "",
  109.         content: "",
  110.         details_image_url: ""
  111.       },
  112.       addFormRules: {
  113.         title: [{ required: true, message: "请输入标题", trigger: "blur" }],
  114.         image_url: [
  115.           { required: true, message: "请输入图片地址", trigger: "blur" }
  116.         ],
  117.         content: [{ required: true, message: "请输入内容", trigger: "blur" }],
  118.         details_image_url: [
  119.           { required: true, message: "请输入图片详情", trigger: "blur" }
  120.         ]
  121.       },
  122.       editDialogVisible: false,
  123.       editFormData: {
  124.         id: null,
  125.         title: "",
  126.         image_url: "",
  127.         content: "",
  128.         details_image_url: ""
  129.       },
  130.       editFormRules: {
  131.         title: [{ required: true, message: "请输入标题", trigger: "blur" }],
  132.         image_url: [
  133.           { required: true, message: "请输入图片地址", trigger: "blur" }
  134.         ],
  135.         content: [{ required: true, message: "请输入内容", trigger: "blur" }],
  136.         details_image_url: [
  137.           { required: true, message: "请输入图片详情", trigger: "blur" }
  138.         ]
  139.       }
  140.     };
  141.   },
  142.   mounted() {
  143.     this.getData();
  144.   },
  145.   methods: {
  146.     getData() {
  147.       axios.get(" http://127.0.0.1:8005/web_drf/coreBusinessView/").then(
  148.         response => {
  149.           console.log(response.data);
  150.           this.tableData = response.data;
  151.         },
  152.         error => {
  153.           console.log("error");
  154.         }
  155.       );
  156.     },
  157.     handleSizeChange(size) {
  158.       this.pagesize = size;
  159.     },
  160.     handleCurrentChange(currentPage) {
  161.       this.currentPage = currentPage;
  162.     },
  163.     showAddDialog() {
  164.       this.addDialogVisible = true;
  165.     },
  166.     submitAddForm() {
  167.       this.$refs.addForm.validate(valid => {
  168.         if (valid) {
  169.           axios
  170.             .post(
  171.               " http://127.0.0.1:8005/web_drf/coreBusinessView/",
  172.               this.addFormData
  173.             )
  174.             .then(response => {
  175.               console.log("新增成功", response.data);
  176.               this.addDialogVisible = false;
  177.               this.getData();
  178.               this.addFormData = {
  179.                 title: "",
  180.                 image_url: "",
  181.                 content: "",
  182.                 details_image_url: ""
  183.               };
  184.             })
  185.             .catch(error => {
  186.               console.error("新增失败", error);
  187.             });
  188.         }
  189.       });
  190.     },
  191.     confirmDelete(book) {
  192.       MessageBox.confirm("确定删除该条记录吗?", "提示", {
  193.         confirmButtonText: "确定",
  194.         cancelButtonText: "取消",
  195.         type: "warning"
  196.       })
  197.         .then(() => {
  198.           this.deleteBook(book);
  199.         })
  200.         .catch(() => {
  201.           // 取消删除操作
  202.         });
  203.     },
  204.     deleteBook(book) {
  205.       const url = ` http://127.0.0.1:8005/web_drf/coreBusinessView/${book.id}/`;
  206.       console.log(book.id);
  207.       axios
  208.         .delete(url)
  209.         .then(response => {
  210.           console.log("删除成功");
  211.           this.getData();
  212.         })
  213.         .catch(error => {
  214.           console.error("删除失败", error);
  215.         });
  216.     },
  217.     editBook(book) {
  218.       this.editFormData = { ...book };
  219.       this.editDialogVisible = true;
  220.     },
  221.     submitEditForm() {
  222.       this.$refs.editForm.validate(valid => {
  223.         if (valid) {
  224.           const url = ` http://127.0.0.1:8005/web_drf/coreBusinessView/${this.editFormData.id}/`;
  225.           axios
  226.             .put(url, this.editFormData)
  227.             .then(response => {
  228.               console.log("编辑成功", response.data);
  229.               this.editDialogVisible = false;
  230.               this.getData();
  231.             })
  232.             .catch(error => {
  233.               console.error("编辑失败", error);
  234.             });
  235.         }
  236.       });
  237.     }
  238.   }
  239. };
  240. </script>
  241. <style>
  242. .pagination {
  243.   margin-top: 20px;
  244.   text-align: center;
  245. }
  246. </style>
复制代码
业务范围管理页面效果图

(2)业务范围管理系统后端代码views

  1. from rest_framework.response import Response
  2. from rest_framework.views import APIView
  3. from rest_framework import serializers
  4. from webapp.models import CoreBusiness
  5. class coreBusinessSerializers(serializers.ModelSerializer):
  6.     class Meta:
  7.         model = CoreBusiness
  8.         fields = '__all__'
  9. class coreBusinessView(APIView):
  10.     def get(self, request):
  11.         coreBusiness = CoreBusiness.objects.all()
  12.         ser = coreBusinessSerializers(instance=coreBusiness, many=True)
  13.         print(ser.data)
  14.         return Response(ser.data)
  15.     def post(self, request):
  16.         ser = coreBusinessSerializers(data=request.data)
  17.         if ser.is_valid():
  18.             CoreBusiness.objects.create(**ser.validated_data)
  19.             return Response(ser.validated_data)
  20.         else:
  21.             return Response(ser.errors)
  22. class coreBusinessdetailview(APIView):
  23.     def get(self, request, pk):
  24.         coreBusiness = CoreBusiness.objects.get(pk=pk)
  25.         ser = coreBusinessSerializers(instance=coreBusiness, many=False)
  26.         return Response(ser.data)
  27.     def put(self, request, pk):
  28.         ser = coreBusinessSerializers(data=request.data)
  29.         if ser.is_valid():
  30.             CoreBusiness.objects.filter(pk=pk).update(**ser.validated_data)
  31.             return Response(ser.validated_data)
  32.         else:
  33.             return Response(ser.errors)
  34.     def delete(self, request, pk):
  35.         CoreBusiness.objects.get(pk=pk).delete()
  36.         return Response('删除成功')
复制代码
(3)设置子路由


(4)在主路由中设置该app(主路由跟setting在同一个文件夹)


7.创建数据库表

在恣意一个models中都可以创建数据库表
  1. from django.db import models
  2. # 联系我们表
  3. class Contact(models.Model):
  4.     id = models.AutoField(primary_key=True)
  5.     company_name = models.CharField(max_length=100, verbose_name='公司名称')
  6.     phone = models.CharField(max_length=20, verbose_name='电话')
  7.     address = models.CharField(max_length=200, verbose_name='地址')
  8.     email = models.CharField(max_length=255, verbose_name='邮箱')
  9.     class Meta:
  10.         db_table = 'contact'
复制代码
创建表完成之后举行数据库的迁移,在项目的根目录下的控制台举行
  1. python manage.py makemigrations
  2. python manage.py migrate
复制代码
8.启动vue项目

  1. npm run dev
复制代码
 9.打开浏览器访问http://localhost:8080/#/user/login/ 即可登录


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表