当前位置:   article > 正文

Python Web 前后端分离 后台管理系统 Django+vue(完整代码)_python+django+vue搭建前后端分离项目

python+django+vue搭建前后端分离项目

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

以管理员身份打开命令行界面,进入任意一个想要创建项目的文件夹
 

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项目

npm run dev

9.打开浏览器访问http://localhost:8080/#/user/login/ 即可登录

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/879817
推荐阅读
相关标签
  

闽ICP备14008679号