Python Django + Layui前后端管理系统 完整代码

1.查看效果图

2.创建表,在models.py中进行操作

建好表之后使用python manage.py makemigrations,python manage.py migrate进行数据库迁移

3.登录及注册的实现,效果图及完整代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% load static %}
    <link rel="stylesheet" href='{% static "bootstrap/css/bootstrap.min.css" %}'>
    <link rel="stylesheet" type="text/css" href='{% static "admin/css/login2.css" %}'>
    <title>环保公司</title>
    <style>
        .centered {
            position: absolute; /* 使用绝对定位 */
            top: 50%; /* 使元素上边缘距离页面顶部的距离为屏幕高度的一半 */
            left: 46%; /* 使元素左边缘距离页面左边的距离为屏幕宽度的一半 */
            transform: translate(-50%, -50%); /* 通过transform属性使元素的中心点与页面的中心点对齐 */
            text-align: center; /* 设置文本居中 */
        }
    </style>
</head>
<body style="background: linear-gradient(to right, #d3aff5, #8fd38f);">
<h1 class="centered">后台管理系统</h1>
<div class="content">
    <div class="login">
        <span class="title">
            登录
        </span>
        <form class="form-horizontal" action="{% url 'user:login' %}" method="POST">
            {% csrf_token %}
            <div class="form-group">
                <div class="col-sm-12">
                    <input class="form-control" id="username" name="username" placeholder="用户名">
                </div>
            </div>
            <div class="form-group">
                <div class="col-sm-12">
                    <input class="form-control" id="password" name="password" type="password" placeholder="密码">

                </div>
            </div>

            {% if messages %}
                {% for message in messages %}
                    <div style="color:red;padding-left:15px">{{ message }}</div>
                {% endfor %}
            {% endif %}

            <button type="submit" style="width: 100%; background-color: #64af5f; margin-top: 15px; color: #ffffff"
                    class="btn btn-default">登录
            </button>
            <a style="width: 100%; background-color: #64af5f; margin-top: 15px; color: #ffffff"
                    class="btn btn-default" href="{% url 'user:register' %}">注册
            </a>
        </form>
    </div>
</div>
<footer style="width: 100%; position: absolute; bottom: 0; font-size: 12px; display: flex; justify-content: center">
    Copyright©️2016-2021 环保公司 All Rights Reserved. | 蜀ICP备2020029736号
</footer>
</body>
</html>

4.实现某一页面(案例页面)的增删改查的前后端完整代码

import datetime
import json
from django.core.paginator import Paginator
from django.shortcuts import render
from django.views.decorators.http import require_GET
from django.db.models import Q
from envapp.models import Case
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.views.decorators.http import require_http_methods
from django.shortcuts import get_object_or_404


@require_GET
def index_case(request):
    page = request.GET.get("page", 1)
    limit = request.GET.get("limit", 10)  # 获取每页条数
    key = request.GET.get("key")
    page_obj = Case.objects.all().order_by("-id")

    if key:
        page_obj = page_obj.filter(Q(content__contains=key))

    paginator = Paginator(page_obj, limit)

    if page:
        page_obj = paginator.get_page(page)

    # 将日期时间字段转换为指定格式
    for item in page_obj.object_list:
        item.time = item.time.strftime('%Y-%m-%d')
    data = {
        'code': 0,
        'msg': '信息查询成功',
        'count': paginator.count,
        'data': list(page_obj.object_list.values())  # 获取当前页对象列表,并转换为字典列表
    }

    response = JsonResponse(data)
    response['Access-Control-Allow-Origin'] = '*'  # 允许所有域名进行跨域访问
    response['Content-Security-Policy'] = "frame-ancestors https://m.wo.cn"  # 添加 Content-Security-Policy 头部
    return response


def case(request):
    return render(request, 'case/case_index.html')


def case_add(request):
    return render(request, 'case/case_add.html')


@require_POST
def case_post(request):
    try:
        js = request.body.decode('utf8')
        data = json.loads(js)

        # 将日期字符串转换为 datetime 对象
        data['time'] = datetime.datetime.strptime(data['time'], '%Y-%m-%d')

        # 创建 Case 对象并保存
        new = Case(**data)
        new.save()

        return JsonResponse({
            'code': 0,
            'msg': '新增数据成功'
        })
    except Exception as e:
        return JsonResponse({
            'code': -1,
            'msg': '新增数据失败: {}'.format(str(e))
        })


@require_http_methods(["PUT"])
def case_update(request, sid):
    if request.method == 'PUT':
        data = json.loads(request.body)

        data['time'] = datetime.datetime.strptime(data['time'], '%Y-%m-%d')
        new = get_object_or_404(Case, id=sid)

        try:
            # 使用点操作符为对象的属性赋值
            new.title = data['title']
            new.content = data['content']
            new.time = data['time']
            new.category = data['category']
            new.image_link = data['image_link']

            # 保存对象更改
            new.save()

            return JsonResponse({
                'code': 0,
                'msg': '修改数据成功'
            })
        except Exception as e:
            return JsonResponse({
                'code': -1,
                'msg': '修改数据失败: {}'.format(str(e))
            })


@require_http_methods(["DELETE"])
def case_del(request, sid):
    new = get_object_or_404(Case, id=sid)
    try:
        new.delete()
        return JsonResponse({
            'code': 0,
            'msg': '删除数据成功'
        })
    except Exception as e:
        return JsonResponse({
            'code': -1,
            'msg': '删除数据失败: {}'.format(str(e))
        })

案例页面的首页(前端代码)

{% extends 'layout.html' %}
{% block content %}
    <script type="text/html" id="toolbar">
        <div class="layui-btn-container">
            <button class="layui-btn layui-btn-sm" lay-event="add">添加</button>
            <button class="layui-btn layui-btn-sm" lay-event="delete_many">删除</button>
        </div>
    </script>
    <!-- 表头某列 templet 属性指向的模板 -->
    <script type="text/html" id="tools">
        <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
    </script>


    <form class="layui-form" action="" id="form_edit" lay-filter="form_edit" style="margin-top: 20px;display: none">
        <div class="layui-form-item" style="display: none">
            <label class="layui-form-label">ID</label>
            <div class="layui-input-block">
                <input type="text" name="id" lay-verify="required" autocomplete="off" placeholder="请输入"
                       class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">标题</label>
            <div class="layui-input-block">
                <input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入"
                       class="layui-input">
            </div>
        </div>

        <div class="layui-form-item">
            <label class="layui-form-label">内容</label>
            <div class="layui-input-block">
                <textarea name="content" class="layui-textarea" placeholder="请输入内容"></textarea>
            </div>
        </div>
        <div class="layui-form-item">
            <div class="layui-inline">
                <label class="layui-form-label">时间</label>
                <div class="layui-input-inline">
                    <input type="text" class="layui-input" name="time" id="time"
                           placeholder="" autocomplete="off" lay-verify="required">
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">分类</label>
            <div class="layui-input-block">
                <textarea name="category" class="layui-textarea" placeholder="请输入"></textarea>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">图片链接</label>
            <div class="layui-input-block">
                <textarea name="image_link" class="layui-textarea" placeholder="请输入"></textarea>
            </div>
        </div>

        <div class="layui-form-item">
            <div class="layui-input-block">
                <button type="submit" class="layui-btn" lay-submit lay-filter="edit-commit">立即提交</button>
                <button type="reset" class="layui-btn layui-btn-primary">重置</button>
            </div>
        </div>
    </form>

    <table class="layui-hide" id="ID-table-demo-page"></table>
    <script type="text/html" id="ID-table-demo-page-pagebar">

</script>
{% endblock %}

{% block js %}
    <script>

        // 编辑提交的方法
        const change_case = async (id, data) => {
            const options = {
                method: 'PUT',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(data)
            }
            const response = await fetch(`/web/case_update/${id}/`, options)
            return await response.json()
        }
        layui.use('table', function () {
            var table = layui.table;
            var $ = layui.$;
            var form = layui.form;
            var laydate = layui.laydate;

            // 创建渲染实例
            table.render({
                elem: '#ID-table-demo-page',
                url: '/web/index_case/', // 此处为静态模拟数据,实际使用时需换成真实接口
                page: {
                    layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
                    //curr: 5, //设定初始在第 5 页
                    groups: 1, //只显示 1 个连续页码
                    first: false, //不显示首页
                    last: false //不显示尾页
                },
                pagebar: '#ID-table-demo-page-pagebar', // 分页栏模板
                toolbar: '#toolbar',
                cols: [[
                    {field: 'id', title: 'ID', width: 60, sort: true},
                    {field: 'title', title: '标题', width: 100},
                    {field: 'content', title: '内容', minWidth: 160},
                    {field: 'category', title: '分类', minWidth: 160},
                    {field: 'time', title: '时间', width: 200},
                    {field: 'image_link', title: '图片链接', width: 120},
                    {title: '操作', width: 120, templet: '#tools'},
                ]]
            });
            // 底部分页栏事件
            table.on('toolbar(ID-table-demo-page)', function (obj) {
                var options = obj.config;
                var checkStatus = table.checkStatus(options.id);

                switch (obj.event) {
                    case 'add':
                        window.show_add()
                        break;
                    case 'delete_many':
                        window.delete_many(obj)
                        break;
                }
            });
            window.show_add = function () {
                {#layer.msg('添加')#}
                layer.open(({
                    type: 2,
                    title: '新增新闻',
                    shadeClose: true,
                    maxmin: true,
                    area: ['900px', '600px'],
                    content: '/web/case_add/'
                }))
            }
            window.delete_many = function () {
                layer.msg('批量删除')
            }
            // 单元格工具事件
            table.on('tool(ID-table-demo-page)', function (obj) {
                var layEvent = obj.event; // 获得元素对应的 lay-event 属性值
                if (layEvent === 'edit') { //编辑
                    window.show_edit(obj)
                } else if (layEvent === 'del') { //删除
                    layer.confirm('确定删除吗?', function (index) {
                        layer.close(index);
                        window.del_case(obj)
                    });
                }
            });

            // 日期时间选择器
            laydate.render({
                elem: '#time',
                type: 'date',
                format: 'yyyy-MM-dd'
            });

            window.show_edit = (obj) => {
                console.log(obj.data)
                form.val('form_edit', obj.data);

                layer.open({
                    type: 1,
                    area: ['900px', '600px'],
                    content: $('#form_edit'), // 捕获的元素
                    shade: 0.0
                });
            }

            const del_case_api = async (id) => {
                const options = {
                    method: 'DELETE',
                    headers: {'Content-Type': 'application/json'},
                }
                const response = await fetch(`/web/case_del/${id}/`, options)
                return await response.json()
            }

            window.del_case = (obj) => {
                // console.log(obj)
                del_case_api(obj.data.id).then(function (ret) {
                    // 提交成功之后的回调
                    if (!ret.code) {
                        layer.msg(ret.msg, {
                            icon: 1,
                            time: 1000,
                        }, function () {
                            table.reload('ID-table-demo-page');
                        });
                    } else {
                        layer.msg(ret.msg, {
                            icon: 2,
                            time: 1000,
                        });
                    }
                })
            }

            // 提交事件
            form.on('submit(edit-commit)', function (data) {
                var field = data.field; // 获取表单字段值

                change_case(field.id, field).then(function (ret) {

                    // 提交成功之后的回调
                    if (!ret.code) {
                        layer.msg(ret.msg, {
                            icon: 1,
                            time: 1000,
                        }, function () {
                            layer.closeAll('page');
                            table.reload('ID-table-demo-page');
                        });
                    } else {
                        layer.msg(ret.msg, {
                            icon: 2,
                            time: 1000,
                        });
                    }
                })

                return false; // 阻止默认 form 跳转
            });
        });
    </script>
{% endblock js %}

案例页面的增加及编辑代码

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>新增</title>
    <link rel="stylesheet" href="{% static 'css/layui.css' %}">

</head>
<body>

<form class="layui-form" action="" lay-filter="form_add" style="margin-top: 20px">
    <div class="layui-form-item">
        <label class="layui-form-label">标题</label>
        <div class="layui-input-block">
            <input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入"
                   class="layui-input">
        </div>
    </div>

    <div class="layui-form-item">
        <label class="layui-form-label">内容</label>
        <div class="layui-input-block">
            <textarea name="content" class="layui-textarea" placeholder="请输入内容"></textarea>
        </div>
    </div>
    <div class="layui-form-item">
        <div class="layui-inline">
            <label class="layui-form-label">时间</label>
            <div class="layui-input-inline">
                <input type="text" class="layui-input" name="time" id="time"
                       placeholder="" autocomplete="off" lay-verify="required">
            </div>
        </div>
    </div>
           <div class="layui-form-item">
            <label class="layui-form-label">分类</label>
            <div class="layui-input-block">
                <textarea name="category" class="layui-textarea" placeholder="请输入"></textarea>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">图片链接</label>
            <div class="layui-input-block">
                <textarea name="image_link" class="layui-textarea" placeholder="请输入"></textarea>
            </div>
        </div>

    <div class="layui-form-item">
        <div class="layui-input-block">
            <button type="submit" class="layui-btn" lay-submit lay-filter="add-commit">立即提交</button>
            <button type="reset" class="layui-btn layui-btn-primary">重置</button>
        </div>
    </div>
</form>

<script src="{% static 'layui.js' %}"></script>

<script>
    // 新增提交的方法
    const add_news = async (data) => {
        const options = {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify(data)
        }
        const response = await fetch('/web/case_post/', options)
        return await response.json()
    }

    layui.use(function () {
        var $ = layui.$
        var form = layui.form
        var laydate = layui.laydate;

        // 日期时间选择器
        laydate.render({
            elem: '#time',
            type: 'date',
            format:'yyyy-MM-dd'
        });

        // 提交事件
        form.on('submit(add-commit)', function (data) {
            var field = data.field; // 获取表单字段值
            console.log(field)
            // 此处可执行 Ajax 等操作
            add_news(field).then(function (ret) {

                // 提交成功之后的回调
                if (!ret.code) {
                    layer.msg(ret.msg, {
                        icon: 1,
                        time: 1000,
                    }, function () {
                        parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
                        parent.layui.table.reload('case/');
                    });
                } else {
                    layer.msg(ret.msg, {
                        icon: 2,
                        time: 1000,
                    });
                }
            })
            return false; // 阻止默认 form 跳转
        });
    })
</script>
</body>
</html>

5.配置主路由及子路由

主路由是在跟setting同级的urls中,子路由在注册的app中的urls中,没有则自己创建

6.配置setting

配置数据库,可以使用mysql,也可以使用自带的sqlite3

配置static和跨域问题

APPEND_SLASH = False

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

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

7.目录结构

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Play_Sai

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

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

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

打赏作者

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

抵扣说明:

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

余额充值