Python Web 前后端分离 后台管理系统 Django+vue(完整代码)

1.前后端分离的架构

在前后端分离的架构中,前端和后端分别作为独立的项目进行开发和部署。前端项目通过API与后端项目进行通信。

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

2.创建django项目及vue项目

创建app的时候需要进入项目的目录下  win10 cd xmmc

django-admin startproject xmmc
django-admin startapp app01

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

vue create vueproject

然后按自己的需求选择,可以去专门搜一下创建vue的教程

3.配置setting

(1)配置数据库

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 加载mysql引擎
        'NAME': 'db_goods',  # 数据库名称
        'USER': 'root',  # mysql账户名
        'PASSWORD': '123456',  # mysql账户密码
        'PORT': 3306,  # 端口号
        'HOST': 'localhost'
    }
}

(2)配置模板文件

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        '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',
            ],
        },
    },
]

(3)配置静态文件

STATIC_URL = 'static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

(4)注册app(使用创建 django-admin startapp app名称)

(5)解决跨域问题

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',
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

# 允许所有的请求头
CORS_ALLOW_HEADERS = ('*')

4.查看目录结构

web_django/
├── static/
├── templates/
├── user/
│   ├── migrations/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   ├── views.py
├── web_django/
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   ├── wsgi.py
├── webapp/
│   ├── migrations/
│   ├── views/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   ├── views.py

5.前后端实现登录

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

<template>
  <div class="login-background">
    <div class="login-container">
      <el-card class="box-card" style="opacity: 0.9;">
        <h2>登录</h2>
        <el-form
          :model="ruleForm"
          status-icon
          :rules="rules"
          ref="ruleForm"
          label-position="left"
          label-width="70px"
          class="login-form"
        >
          <el-form-item label="用户名" prop="uname">
            <el-input v-model="ruleForm.uname"></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input
              type="password"
              v-model="ruleForm.password"
              autocomplete="off"
            ></el-input>
          </el-form-item>
        </el-form>
        <div class="btn-group">
          <el-button type="primary" @click="submitForm('ruleForm')"
            >登录</el-button
          >
          <el-button @click="resetForm('ruleForm')">重置</el-button>
          <router-link to="/register">
            <el-button style="margin-left:10px">注册</el-button>
          </router-link>
        </div>
      </el-card>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      ruleForm: {
        uname: "",
        password: "",
      },
      rules: {
        uname: [
          { required: true, message: "用户名不能为空!", trigger: "blur" },
        ],
        password: [
          { required: true, message: "密码不能为空!", trigger: "blur" },
        ],
      },
    };
  },
  methods: {
    async submitForm(formName) {
      try {
        const response = await axios.post('http://127.0.0.1:8005/user/login/', this.ruleForm);
        // 在这里处理后端响应
        console.log(response.data);
        if (response.data.success) {
          sessionStorage.setItem('username', JSON.stringify(response.data))
          // 登录成功,跳转到 Index 页面
          this.$router.push('/components/News');
        } else {
          // 登录失败,显示错误消息或其他处理
          console.error('登录失败:', response.data.message);
        }
      } catch (error) {
        console.error('提交表单时发生错误:', error);
      }
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
  },
};
</script>

<style scoped>
.login-background {
  background-image: url('https://pic4.zhimg.com/v2-b730c73ebd78bd5f22293aab0d343f4b_r.jpg?source=1940ef5c');
  background-size: cover;
  background-position: center;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.box-card {
  width: 400px;
}

.login-form {
  margin: auto;
}

.btn-group {
  margin-top: 20px;
}
</style>

登录效果图

(2)编写登录后端views(视图文件)

from django.http import JsonResponse
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
import json


def login_view(request):
    # if request.method == 'GET':

    if request.method == 'POST':
        js = request.body.decode('utf8')
        data = json.loads(js)
        username = data['uname']
        password = data['password']

        # 使用 Django 自带的 authenticate 方法验证用户身份
        user = authenticate(request, username=username, password=password)

        if user is not None:
            # 登录成功,将用户添加到当前会话中
            login(request, user)

            print(user)
            return JsonResponse({'code': 200, 'success': True, 'message': '登录成功', 'username': str(user)})
        else:
            # 登录失败,返回错误消息
            return JsonResponse({'code': 500, 'success': False, 'message': '用户名或密码错误', })

    # 如果不是 POST 请求,则返回错误消息
    return JsonResponse({'success': False, 'message': '只支持 POST 请求'})



def register_view(request):
    if request.method == 'POST':
        # 从请求体中获取JSON数据
        js = request.body.decode('utf8')
        data = json.loads(js)
        print(data)
        username = data['uname']
        password = data['password']


        # 检查用户名是否已经存在
        if User.objects.filter(username=username).exists():
            return JsonResponse({'code': 400, 'success': False, 'message': '用户名已存在'})

        # 创建用户
        user = User.objects.create_user(username=username, password=password)

        # 返回成功消息
        return JsonResponse({'code': 200, 'success': True, 'message': '注册成功', 'username': username})

    # 如果不是 POST 请求,则返回错误消息
    return JsonResponse({'code': 405, 'success': False, 'message': '只支持 POST 请求'})

(3)子视图文件(在user app中创建一个urls)

from . import views

from django.urls import path, re_path

urlpatterns = [
    path('login/', views.login_view, name='login'),
    path('register/', views.register_view, name='register'),
]

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

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

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

<template>
  <div>
    <el-row style="height: 50px;">
      <el-col :span="1" class="grid">
        <el-button
          type="success"
          @click="showAddDialog"
          icon="el-icon-circle-plus-outline"
          size="mini"
          round
        >新增</el-button>
      </el-col>
    </el-row>
    <el-dialog title="新增" :visible.sync="addDialogVisible" width="42%">
      <el-form :model="addFormData" :rules="addFormRules" ref="addForm" label-width="120px">
        <el-form-item label="标题" prop="title">
          <el-input v-model="addFormData.title"></el-input>
        </el-form-item>
        <el-form-item label="图片链接" prop="image_url">
          <el-input v-model="addFormData.image_url"></el-input>
        </el-form-item>
        <el-form-item label="内容" prop="content">
          <el-input v-model="addFormData.content"></el-input>
        </el-form-item>
        <el-form-item label="图片详情链接" prop="details_image_url">
          <el-input v-model="addFormData.details_image_url"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitAddForm">确 定</el-button>
      </span>
    </el-dialog>

    <el-dialog title="编辑" :visible.sync="editDialogVisible" width="40%">
      <el-form :model="editFormData" :rules="editFormRules" ref="editForm" label-width="100px">
        <el-form-item label="标题" prop="title">
          <el-input v-model="editFormData.title"></el-input>
        </el-form-item>
        <el-form-item label="图片链接" prop="image_url">
          <el-input v-model="editFormData.image_url"></el-input>
        </el-form-item>
        <el-form-item label="内容" prop="content">
          <el-input v-model="editFormData.content"></el-input>
        </el-form-item>
        <el-form-item label="图片详情链接" prop="details_image_url">
          <el-input v-model="editFormData.details_image_url"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitEditForm">确 定</el-button>
      </span>
    </el-dialog>

    <el-table
      :data="tableData.slice((currentPage-1)*pagesize,currentPage*pagesize)"
      style="width: 100%; margin-top: 10px;"
      border
      stripe
      ref="multipleTable"
      tooltip-effect="dark"
    >
      <el-table-column label="序号" type="index" width="80px" align="center"></el-table-column>

      <el-table-column prop="title" width="100px" label="标题"></el-table-column>
      <el-table-column prop="image_url" width="150px" label="图片链接"></el-table-column>
      <el-table-column prop="content" width="120px" label="内容"></el-table-column>
      <el-table-column prop="details_image_url" label="图片详情链接"></el-table-column>
      <el-table-column width="190px" label="操作">
        <template slot-scope="scope">
          <el-button type="primary" icon="el-icon-edit" size="mini" @click="editBook(scope.row)">编辑</el-button>
          <el-button
            icon="el-icon-delete"
            size="mini"
            type="danger"
            @click="confirmDelete(scope.row)"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <div class="pagination">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[5, 10, 20, 40]"
        :page-size="pagesize"
        layout="total, sizes,prev, pager, next"
        :total="tableData.length"
        prev-text="上一页"
        next-text="下一页"
      ></el-pagination>
    </div>
  </div>
</template>

<script>
import axios from "axios";
import { MessageBox } from "element-ui";

export default {
  name: "app",
  data() {
    return {
      currentPage: 1, // 默认显示页面为1
      pagesize: 5, // 每页的数据条数
      tableData: [], // 需要 data 定义一些,tableData 定义一个空数组,请求的数据都是存放这里面
      addDialogVisible: false,
      activeIndex2: "1",
      addFormData: {
        title: "",
        image_url: "",
        content: "",
        details_image_url: ""
      },
      addFormRules: {
        title: [{ required: true, message: "请输入标题", trigger: "blur" }],
        image_url: [
          { required: true, message: "请输入图片地址", trigger: "blur" }
        ],
        content: [{ required: true, message: "请输入内容", trigger: "blur" }],
        details_image_url: [
          { required: true, message: "请输入图片详情", trigger: "blur" }
        ]
      },
      editDialogVisible: false,
      editFormData: {
        id: null,
        title: "",
        image_url: "",
        content: "",
        details_image_url: ""
      },
      editFormRules: {
        title: [{ required: true, message: "请输入标题", trigger: "blur" }],
        image_url: [
          { required: true, message: "请输入图片地址", trigger: "blur" }
        ],
        content: [{ required: true, message: "请输入内容", trigger: "blur" }],
        details_image_url: [
          { required: true, message: "请输入图片详情", trigger: "blur" }
        ]
      }
    };
  },
  mounted() {
    this.getData();
  },
  methods: {
    getData() {
      axios.get(" http://127.0.0.1:8005/web_drf/coreBusinessView/").then(
        response => {
          console.log(response.data);
          this.tableData = response.data;
        },
        error => {
          console.log("error");
        }
      );
    },
    handleSizeChange(size) {
      this.pagesize = size;
    },
    handleCurrentChange(currentPage) {
      this.currentPage = currentPage;
    },
    showAddDialog() {
      this.addDialogVisible = true;
    },
    submitAddForm() {
      this.$refs.addForm.validate(valid => {
        if (valid) {
          axios
            .post(
              " http://127.0.0.1:8005/web_drf/coreBusinessView/",
              this.addFormData
            )
            .then(response => {
              console.log("新增成功", response.data);
              this.addDialogVisible = false;
              this.getData();
              this.addFormData = {
                title: "",
                image_url: "",
                content: "",
                details_image_url: ""
              };
            })
            .catch(error => {
              console.error("新增失败", error);
            });
        }
      });
    },
    confirmDelete(book) {
      MessageBox.confirm("确定删除该条记录吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.deleteBook(book);
        })
        .catch(() => {
          // 取消删除操作
        });
    },
    deleteBook(book) {
      const url = ` http://127.0.0.1:8005/web_drf/coreBusinessView/${book.id}/`;
      console.log(book.id);
      axios
        .delete(url)
        .then(response => {
          console.log("删除成功");
          this.getData();
        })
        .catch(error => {
          console.error("删除失败", error);
        });
    },
    editBook(book) {
      this.editFormData = { ...book };
      this.editDialogVisible = true;
    },
    submitEditForm() {
      this.$refs.editForm.validate(valid => {
        if (valid) {
          const url = ` http://127.0.0.1:8005/web_drf/coreBusinessView/${this.editFormData.id}/`;
          axios
            .put(url, this.editFormData)
            .then(response => {
              console.log("编辑成功", response.data);
              this.editDialogVisible = false;
              this.getData();
            })
            .catch(error => {
              console.error("编辑失败", error);
            });
        }
      });
    }
  }
};
</script>

<style>
.pagination {
  margin-top: 20px;
  text-align: center;
}
</style>

业务范围管理页面效果图

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

from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import serializers

from webapp.models import CoreBusiness


class coreBusinessSerializers(serializers.ModelSerializer):
    class Meta:
        model = CoreBusiness
        fields = '__all__'


class coreBusinessView(APIView):

    def get(self, request):
        coreBusiness = CoreBusiness.objects.all()
        ser = coreBusinessSerializers(instance=coreBusiness, many=True)
        print(ser.data)
        return Response(ser.data)

    def post(self, request):
        ser = coreBusinessSerializers(data=request.data)
        if ser.is_valid():
            CoreBusiness.objects.create(**ser.validated_data)
            return Response(ser.validated_data)
        else:
            return Response(ser.errors)


class coreBusinessdetailview(APIView):
    def get(self, request, pk):
        coreBusiness = CoreBusiness.objects.get(pk=pk)
        ser = coreBusinessSerializers(instance=coreBusiness, many=False)
        return Response(ser.data)

    def put(self, request, pk):
        ser = coreBusinessSerializers(data=request.data)
        if ser.is_valid():
            CoreBusiness.objects.filter(pk=pk).update(**ser.validated_data)
            return Response(ser.validated_data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        CoreBusiness.objects.get(pk=pk).delete()
        return Response('删除成功')

(3)配置子路由

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

7.创建数据库表

在任意一个models中都可以创建数据库表

from django.db import models


# 联系我们表
class Contact(models.Model):
    id = models.AutoField(primary_key=True)
    company_name = models.CharField(max_length=100, verbose_name='公司名称')
    phone = models.CharField(max_length=20, verbose_name='电话')
    address = models.CharField(max_length=200, verbose_name='地址')
    email = models.CharField(max_length=255, verbose_name='邮箱')

    class Meta:
        db_table = 'contact'

创建表完成之后进行数据库的迁移,在项目的根目录下的控制台进行

python manage.py makemigrations
python manage.py migrate

8.启动vue项目

npm run dev

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

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: Python是一种高级编程语言,可以用来开发各种类型的应用程序。DjangoPython的一个开发框架,它提供了一套完整的工具和函数,用于快速开发高质量的Web应用程序。Vue是一种JavaScript框架,用于构建用户界面。 我们可以使用PythonDjango来开发一个后台管理系统,该系统可以用于管理各种数据和业务逻辑。使用Django的ORM(对象关系映射)功能,我们可以轻松地组织和管理数据库中的数据。我们可以定义模型类来表示数据库表,然后使用Django提供的视图和模板来呈现和操作这些数据。 对于PDF文件的处理,可以使用Python中的第三方库来实现。例如,可以使用PyPDF2库来提取PDF文件的内容,或者使用ReportLab库来生成PDF文件。 在后台管理系统中,我们可以使用Vue来构建用户界面。Vue的组件化开发模式可以帮助我们清晰地划分界面,提高开发效率。通过Vue的数据绑定功能,我们可以实现一个交互式的用户界面,以方便用户对数据进行操作和管理。 总结起来,我们可以使用PythonDjango来开发后台管理系统,然后使用Vue来构建用户界面。在系统中处理PDF文件时,可以使用Python的第三方库来实现相关功能。这样的系统将能够方便地管理数据,并提供一个友好和交互式的用户界面。 ### 回答2: Python是一种强大的编程语言,而DjangoPython的一个开发框架,它能够快速地帮助开发者搭建出高效稳定的后台管理系统。而Vue是一种流行的JavaScript框架,能够实现前端页面与后台数据的交互。 在这个后台管理系统中,我们希望能够实现对PDF文件的管理,以及对其进行操作和展示。具体而言,我们希望实现以下功能: 1. 文件上传和保存:用户可以通过该系统上传PDF文件,并将其保存在后台数据库中进行管理。 2. 文件列表展示:系统能够展示已上传的PDF文件列表,包括文件名称、上传时间等信息。 3. 文件预览:用户可以点击某个文件,在前端页面上进行预览,查看PDF文件内容。 4. 文件下载:用户可以选择下载某个PDF文件到本地,以便查看或者进行其他操作。 5. 文件搜索:系统能够根据用户输入的关键词,对已上传的PDF文件进行搜索,并返回相关结果。 为了实现这些功能,我们可以借助Django的文件上传和数据库操作功能。前端页面可以使用Vue来展示文件列表和搜索框,并通过Vue的组件化和数据绑定特性实现动态更新。而PDF文件的预览和下载功能,则可以使用一些开源的JavaScript库,如PDF.js等。 总的来说,通过PythonDjango框架和Vue前端开发能力,结合PDF的相关JavaScript库,我们能够实现一个功能齐全、操作方便的后台管理系统,提供便捷的PDF文件管理和展示功能。 ### 回答3: Python是一种高级编程语言,Django是一个基于PythonWeb框架,而Vue是一个流行的JavaScript框架。结合这三者,可以实现一个功能强大的后台管理系统,并且支持生成和展示PDF文件。 首先,使用Django搭建后台,可以使用Django的模型和视图来定义和处理数据模型。通过定义模型类,可以创建数据库表格,并通过视图函数来处理用户的请求,并返回相应的数据或页面。 在前端部分,可以使用Vue来构建用户界面和交互逻辑。Vue有很多强大的功能,比如组件化、双向数据绑定和虚拟DOM等,可以提高开发效率和用户体验。可以使用Vue的组件来实现后台管理系统的各种页面和功能模块,比如用户管理、文章管理、数据统计等。 为了支持PDF的生成和展示,可以使用Python的第三方库,比如ReportLab来生成PDF文件。ReportLab提供了丰富的API来创建和编辑PDF,可以用于生成包含动态数据的PDF报告或文档。生成PDF后,可以使用Django的文件管理系统来存储和管理生成的PDF文件,同时可以通过Django的视图函数和模板来展示PDF文件或提供下载功能。 总结来说,使用PythonDjango框架和Vue框架,可以快速开发一个功能丰富的后台管理系统。通过结合Python的第三方库,还可以支持PDF的生成和展示功能。这样的系统既具备了后台数据管理的功能,又提供了良好的用户界面和交互体验,能够满足现代Web应用的需求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Play_Sai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值