号码管理平台-Django

号码管理系统

1.表结构的设计

号码管理平台_django_bootstrap

号码管理平台_django_django_02

一共有三个数据表, 一个号码表, 一个 管理员表,一个部门表, 其中 号码表的 admin 字段和 管理员表存在外键关系, 管理员表中的 depart_id 和 部门表存在外键关系。

2. 创建项目

使用 pycharm 创建一个django 项目,

在终端使用 python manage.py startapp app名称, 创建app, 这里 为了方便使用 sqllite数据库

3. 创建相关的表结构

# app/models.py

from django.db import models

# Create your models here.


class Department(models.Model):
    """ 部门表 """
    title = models.CharField(verbose_name="标题", max_length=16)


class Admin(models.Model):
    """ 管理员表 """
    username = models.CharField(verbose_name="用户名", max_length=32)
    password = models.CharField(verbose_name="密码", max_length=32)

    # 增加一个年龄字段, 创建管理员的时候,不填的话, 默认为空
    age = models.IntegerField(verbose_name="年龄", null=True, blank=True)
    gender = models.CharField(verbose_name="性别",
                              choices=[(1, "男"), (2, "女")])
    depart = models.ForeignKey(verbose_name="部门", to="Department", on_delete=models.CASCADE)


class Phone(models.Model):
    """ 号码表 """
    mobile = models.CharField(verbose_name="手机号", max_length=11)
    price = models.PositiveIntegerField(verbose_name="价格", default=0)

    level = models.SmallIntegerField(
        verbose_name="级别",
        choices=[
            (1, "1级"),
            (2, "2级"),
            (3, "3级"),
            (4, "4级"),
        ],
        default=1
    )

    status_choices = [
        (1, "已使用"),
        (2, "未使用"),
    ]
    status = models.SmallIntegerField(verbose_name="状态", choices=status_choices, default=2)
    admin = models.ForeignKey(verbose_name="管理员", to="Admin", on_delete=models.CASCADE)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.

在项目终端, 使用 python manage.py makemigrations 和 python manage.py migrate 将相关的类模型 映射到数据库

4. 用户登录

  • 基本逻辑
  • 密码 + 密文存储
  • 图片验证码

号码管理平台_django_bootstrap_03

app 下 创建 static 文件夹及其子文件夹,不同类型的代码放到不同的位置

号码管理平台_django_django_04

登录前端页面实现

<!--login.html-->

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static "plugins/jquery/jquery.3.6.min.js" %}">
    <link rel="stylesheet" href="{% static "plugins/bootstrap-5.3.6-dist/css/bootstrap.min.css" %}">
    <script src="{% static "plugins/bootstrap-5.3.6-dist/js/bootstrap.min.js" %}"></script>
    <style>
        .login-box{
            width:400px;
            height: 280px;
            margin-left:auto;
            margin-right:auto;
            border:1px solid #dddddd;
            margin-top:150px;
            padding-left: 20px;
            padding-right: 20px;
        }
        .login-box h2{
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="login-box">
        <h2>用户登录</h2>

        <form method="post" action="/login/" novalidate>
            {% csrf_token %}
          <div class="form-group">
              <label>{{ form.username.label }}</label>
              {{ form.username }}
              <span style="color: red;">{{ form.username.errors.0 }}</span>
          </div>
          <div class="form-group">
            <label>{{ form.password.label }}</label>
              {{ form.password }}
              <span style="color:red;">{{ form.password.errors.0 }}</span>
          </div>
          <div class="form-group">
            <label>{{ form.code.label }}</label>
            <div class="row">
                <div class="col-sm-6">
                    {{ form.code }}
                </div>
                <div class="col-sm-6">
                    <img src="xxx" alt="">
                </div>
            </div>

              <span style="color:red;">{{ form.code.errors.0 }}</span>
          </div>
          <button type="submit" class="btn btn-primary">提交</button>
            <span style="color:red;">{{ error }}</span>
       </form>
    </div>
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
# views.py

from django.shortcuts import render
from django import forms
from django.core.validators import RegexValidator


# Create your views here.

class LoginForm(forms.Form):
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput(attrs={"class":"form-control", "placeholder":"输入用户名"}),
        # validators=[RegexValidator(r'\w{6,}$', '用户名格式错误')]
    )
    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(attrs={"class":"form-control", "placeholder":"输入密码"}),
    )
    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput(attrs={"class":"form-control", "placeholder":"输入验证码"}),
    )


def login(request):
    """ 用户登录"""
    form = LoginForm()

    return render(request, "login.html", {"form": form})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
# urls.py

from django.contrib import admin
from django.urls import path
from number_management import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("login/", views.login, name="login"),
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

5.展示图片验证码

在 项目目录下创建一个 utils 文件夹, 在下面创建一个 check_code.py 用来存放生成图片验证码的脚本,

# 生成图片验证码的脚本, 返回一个 图片对象和一个 图片中文本的字符串, 其中使用到了 pillow 模块
# pip install pillow

from PIL import Image, ImageDraw, ImageFont
import string
import random


class CaptchaGenerator:
    def __init__(self, width=100, height=30, font_size=20):
        """
        初始化验证码生成器。


        Args:
        - width (int): 图片宽度,默认为250像素。
        - height (int): 图片高度,默认为60像素。
        - font_size (int): 字体大小,默认为48像素。
        """
        self.width = width
        self.height = height
        self.font_size = font_size
        self.chars = string.ascii_letters + string.digits  # 验证码字符集合
        self.bgcolor = (255, 255, 255)  # 图片背景颜色
        self.linecolor = (random.randint(0, 128), random.randint(0, 128), random.randint(0, 128))  # 干扰线颜色
        self.dotcolor = (random.randint(0, 128), random.randint(0, 128), random.randint(0, 128))  # 干扰点颜色
        self.fontcolor = (random.randint(0, 128), random.randint(0, 128), random.randint(0, 128))  # 字体颜色


    def generate_captcha(self):
        """
        生成验证码图片和文本。


        Returns:
        - image (PIL.Image.Image): 生成的验证码图片对象。
        - captcha_text (str): 生成的验证码文本。
        """
        captcha_text = ''.join(random.choice(self.chars) for _ in range(4))  # 随机生成验证码文本
        image = Image.new('RGB', (self.width, self.height), self.bgcolor)  # 创建RGB模式的空白图片
        draw = ImageDraw.Draw(image)  # 创建可在图像上绘图的对象


        font = ImageFont.load_default().font_variant(size=self.font_size)  # 加载默认字体并调整大小


        # 绘制干扰线
        for i in range(5):
            x1 = random.randint(0, self.width)
            y1 = random.randint(0, self.height)
            x2 = random.randint(0, self.width)
            y2 = random.randint(0, self.height)
            draw.line((x1, y1, x2, y2), fill=self.linecolor, width=3)


        # 绘制干扰点
        for i in range(200):
            x = random.randint(0, self.width)
            y = random.randint(0, self.height)
            draw.point((x, y), fill=self.dotcolor)


        # 绘制验证码文字,包括阴影效果
        for i, char in enumerate(captcha_text):
            shadow_offset = random.randint(0, 3)
            shadow_color = (0, 0, 0)
            draw.text((20 + i * 20 + shadow_offset, 5 + shadow_offset), char, font=font, fill=shadow_color)  # 绘制阴影效果的文字
            draw.text((20 + i * 20, 5), char, font=font, fill=self.fontcolor)  # 绘制文字


        return image, captcha_text
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.

修改 登录前端代码 图片验证码的位置 img标签的 src 为 "/img/code/"

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static "plugins/jquery/jquery.3.6.min.js" %}">
    <link rel="stylesheet" href="{% static "plugins/bootstrap-5.3.6-dist/css/bootstrap.min.css" %}">
    <script src="{% static "plugins/bootstrap-5.3.6-dist/js/bootstrap.min.js" %}"></script>
    <style>
        .login-box{
            width:400px;
            height: 280px;
            margin-left:auto;
            margin-right:auto;
            border:1px solid #dddddd;
            margin-top:150px;
            padding-left: 20px;
            padding-right: 20px;
        }
        .login-box h2{
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="login-box">
        <h2>用户登录</h2>

        <form method="post" action="/login/" novalidate>
            {% csrf_token %}
          <div class="form-group">
              <label>{{ form.username.label }}</label>
              {{ form.username }}
              <span style="color: red;">{{ form.username.errors.0 }}</span>
          </div>
          <div class="form-group">
            <label>{{ form.password.label }}</label>
              {{ form.password }}
              <span style="color:red;">{{ form.password.errors.0 }}</span>
          </div>
          <div class="form-group">
            <label>{{ form.code.label }}</label>
            <div class="row">
                <div class="col-sm-6">
                    {{ form.code }}
                </div>
                <div class="col-sm-6">
                    
                    <!--修改了下面这里-->
                    <img src="/img/code/" alt="">
                    
                </div>
            </div>

              <span style="color:red;">{{ form.code.errors.0 }}</span>
          </div>
          <button type="submit" class="btn btn-primary">提交</button>
            <span style="color:red;">{{ error }}</span>
       </form>
    </div>
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

urls.py 中 书写 一个视图函数和url 的映射关系

from django.contrib import admin
from django.urls import path
from number_management import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("login/", views.login, name="login"),
    path("img/code/", views.img_code, name="img_code")
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

views.py 中写 生成验证码图片,并返回的 视图函数

from django.shortcuts import render, HttpResponse
from utils.check_code import CaptchaGenerator
from io import BytesIO


def img_code(request):
    # 生成图片
    obj = CaptchaGenerator()
    image_obj, code_str = obj.generate_captcha()
    # 图片内容写入内存, 从内存中读取并返回
    print(code_str)
    stream = BytesIO()
    image_obj.save(stream,'png')
    return HttpResponse(stream.getvalue())
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

效果图片

号码管理平台_django_django_05

6.点击更换图片

<div class="col-sm-6">
    <img src="/img/code/" id="codeImage">
</div>

<!--验证码 img标签设置一个 id-->

<!--利用 jquery id 选择器 获取这个标签, 给这个标签绑定一个点击事件,首先要引入jquery-->

<script src="{% static "plugins/jquery/jquery.3.6.min.js" %}"></script>
<script>
    $(function(){
        $("#codeImage").click(function(){
            // 获取img 标签的 src 属性;
            var url = $(this).attr('src');
            // 设置属性值不同于之前的,相当于向 url 发送了新的请求, 获取了新的图片验证码
            $(this).attr('src', url + "?");
        });
    })

</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

效果, 点击图片, 会更换图片验证码

号码管理平台_django_django_06

7.使用session 保存验证码

更改 获取图片验证码的视图函数,将验证码内容写入到 session 中,方便后面登录时验证码的校验。

def img_code(request):
    # 1.生成图片
    obj = CaptchaGenerator()
    image_obj, code_str = obj.generate_captcha()

    # 2.图片内容写入内存, 从内存中读取并返回
    print(code_str)
    stream = BytesIO()
    image_obj.save(stream,'png')

    # 3.图片的内容写入session 中, 设置 60s 超时
    request.session['image_code'] = code_str
    request.session.set_expiry(60)
    
    return HttpResponse(stream.getvalue())
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

8.用户登录逻辑校验

用户密码存储在数据库中不能使用明文,需要加密, 可以使用 hashlib 的 md5 加密存储到数据库,

进行登录校验的时候,也需要将 密码进行 md5 加密和 存储在数据库中的加密密码进行对比。

在 utils 文件夹下 创建一个 encrypt.py 文件,在其中写 md5 加密的函数

import hashlib
from django.conf import settings


def md5(data_string):
    obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
    obj.update(data_string.encode("utf-8"))
    return obj.hexdigest()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

加密的 key 使用 django settings.py 中的 SECRET_KEY

号码管理平台_django_bootstrap_07

SECRET_KEY = 'django-insecure-0xmex#*uf-^dzkh1d82_g*3%puk#!%nugq*i1-+u5)yenpy+(6'
  • 1.
# views.py
from django.shortcuts import render, HttpResponse, redirect
from django import forms
from django.core.validators import RegexValidator
from utils.check_code import CaptchaGenerator
from io import BytesIO
from number_management import models
from utils.encrypt import md5

# Create your views here.

class LoginForm(forms.Form):
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput(attrs={"class":"form-control", "placeholder":"输入用户名"}),
        # validators=[RegexValidator(r'\w{6,}$', '用户名格式错误')]
    )
    password = forms.CharField(
        label="密码",
        # 设置 render_value=True , 输入验证码错误的时候,保留之前输入的密码
        widget=forms.PasswordInput(attrs={"class":"form-control", "placeholder":"输入密码"}, render_value=True),
    )
    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput(attrs={"class":"form-control", "placeholder":"输入验证码"}),
    )


def login(request):
    """ 用户登录"""
    if request.method == "GET":
        form = LoginForm()
        return render(request, "login.html", {"form": form})
    form = LoginForm(data=request.POST)
    if not form.is_valid():
        return render(request, "login.html", {"form": form})

    # 判断验证码是否正确
    image_code = request.session.get("image_code")
    if not image_code:
        form.add_error("code", "验证码已过期")
        return render(request, "login.html", {"form": form})
    if image_code.upper() != form.cleaned_data['code'].upper():
        form.add_error("code", "验证码错误")
        return render(request, "login.html", {"form": form})

    # 验证码正确, 去数据库校验用户名和密码
    user = form.cleaned_data['username']

    # 密码不能够存储明文的, 可以使用 hashlib 中 的 md5 进行加密
    pwd = form.cleaned_data['password']

    encrypt_password = md5(pwd)
    print(user, encrypt_password)
    admin_object=models.Admin.objects.filter(username=user,password=encrypt_password).first()
    if not admin_object:
        return render(request, "login.html", {"form": form, "error":"用户名或密码错误"})

    request.session['info'] = {"id": admin_object.id, "name": admin_object.username}
    request.session.set_expiry(60 * 60 * 24 * 7)

    return redirect("/home")

def img_code(request):
    # 1.生成图片
    obj = CaptchaGenerator()
    image_obj, code_str = obj.generate_captcha()

    # 2.图片内容写入内存, 从内存中读取并返回
    print(code_str)
    stream = BytesIO()
    image_obj.save(stream,'png')

    # 3.图片的内容写入session 中, 设置 60s 超时
    request.session['image_code'] = code_str
    request.session.set_expiry(60)
    return HttpResponse(stream.getvalue())
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.

6.基于中间件进行用户校验

在项目的 utils 文件夹中写一个middleware.py 写自定义的中间件,用来做用户校验

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect


class AuthMiddleware(MiddlewareMixin):

    def process_request(self, request):
        # 1. 不用登录就可以访问处理
        if request.path_info in ["/login/", "/img/code/"]:
            # return 为空代码继续向后走
            return
        # 2. 获取 session
        info_dict = request.session.get("info")

        # 未登录, 重定向到 login 页面
        if not info_dict:
            return redirect("login")

        # 已登录, 将登录信息储存到 request 中
        request.info_dict = info_dict
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

号码管理平台_django_验证码_08

7.Home页面展示

写一个layout.html 作为母版,母版中写一些公共的内容,例如导航条,

导航条相关的代码从 bootstrp 官方文档中获取,修改成自己需要的样子。

注意 bootstrap依赖于 jquery , 所以也需要引入 jquery,

使用 block 进行占位

<!--layout.html-->

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.css' %}">
    {% block css %}
    	
    {% endblock %}
</head>
<body>
<nav class="navbar navbar-default" style="border-radius:0;">
  <div class="container">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">号码管理系统</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li><a href="#">用户管理</a></li>
        <li><a href="#">号码管理</a></li>
      </ul>
      <ul class="nav navbar-nav navbar-right">
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ request.info_dict.name }} <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">个人资料</a></li>
            <li><a href="#">修改密码</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">注销</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

<div class="container">
    {% block content %}
    	
    {% endblock %}
</div>

<script src="{% static 'plugins/jquery/jquery.3.6.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script>
{% block js %}
	
{% endblock %}
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.

home 页面继承 layout.html (模版继承)

{% extends 'layout.html' %}

{% block content %}
	<h3>欢迎{{ request.info_dict.name }}登录号码管理系统</h3>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

8.注销

修改 layout.html 中的 注销 a 标签的 href 属性,点击 a 标签向 退出登录视图函数发送请求。

<ul class="dropdown-menu">
            <li><a href="#">个人资料</a></li>
            <li><a href="#">修改密码</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="/logout">注销</a></li>
          </ul>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

在 app 中的 views.py 中写一个 退出登录的视图函数

# views.py 
def logout(request):
    # 将session 删除调
    request.session.clear()
    return redirect("/login/")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

urls.py 中的 路由和视图函数的映射

from django.urls import path
from number_management import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("login/", views.login, name="login"),
    path("logout/", views.logout, name="logout"),
    path("img/code/", views.img_code, name="img_code"),
    path("home", views.home, name="home")
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

代码分类, 使结构变的清晰一些。

在 相关的 app 下创建一个 views 文件夹, 根据功能的不同,将不同的 视图函数放到不同的脚本中

号码管理平台_django_bootstrap_09

导入模块时,为了使条理更加的清晰, 一般把内置模块放到 脚本最上面,第三方模块,短的在上面, 长的在下面

然后 自定义模块

号码管理平台_django_验证码_10

urls.py 中的视图函数的导入位置也要做响应的修改

from django.urls import path
from number_management.views import account

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("login/", account.login, name="login"),
    path("logout/", account.logout, name="logout"),
    path("img/code/", account.img_code, name="img_code"),
    path("home", account.home, name="home")
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

9.用户列表

修改 用户管理a 标签的 href 属性,点击 a 标签会向相关的视图函数发送请求,跳转页面

<ul class="nav navbar-nav">
        <li><a href="/admin/list/">用户管理</a></li>
        <li><a href="#">号码管理</a></li>
      </ul>
  • 1.
  • 2.
  • 3.
  • 4.

在 app 下的 views文件夹下创建一个 admin.py 用来存放 号码管理员相关的视图函数

# app/views/admin.py

from django.shortcuts import render
from number_management import models


def admin_list(request):
    """
    用户列表
    :param request:
    :return:
    """
    # [obj, obj, obj]  order_by("-id")  根据id 倒序排序
    queryset = models.Admin.objects.all().order_by("-id")
    # for row in queryset:
        # 如果 models.py 该字段中定义了 choice 对应关系, 使用对象.get_字段名_display() 获取 choice 中设置的
        # 对应的值 例如 row.get_gender_dispaly 可以获取 男或者 女
        # choices=[(1, "男"), (2, "女")]

        # row.depart.title , 跨表查询
        # print(row.username, row.password, row.gender, row.get_gender_display(),row.depart.title)
        # mpx 8fe4282d77a078f5a064fff057288ee9 1 男 IT

    return render(request,"admin_list.html", {"queryset": queryset})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

将相关的管理员信息传递到 html 文件中进行渲染 admin_list.html

{% extends "layout.html"  %}


{% block content %}
	<table class="table table-bordered">
        <thead>
            <tr>
                <th>ID</th>
                <th>name</th>
                <th>gender</th>
                <th>age</th>
                <th>department</th>
            </tr>
        </thead>
        <tbody>
            {% for row in queryset %}
                <tr>
                    <td>{{ row.id }}</td>
                    <td>{{ row.username }}</td>
                    <td>{{ row.get_gender_display }}</td>
                    <td>{{ row.age }}</td>
                    <td>{{ row.depart.title}}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

效果图

号码管理平台_django_bootstrap_11

10.新建用户

在admin_list.html 页面添加一个 a标签,点击跳转到 /admin/add/ 页面, 同时在a 标签的前面添加了一个 bootstrap 官网的 图标

{% extends "layout.html"  %}


{% block content %}
    <!-- 改动的地方-->
    <div style="margin-bottom:10px">
        <a class="btn btn-success" href="/admin/add/">
            <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>新建用户</a>
    </div>
	<table class="table table-bordered">
        <thead>
            <tr>
                <th>ID</th>
                <th>name</th>
                <th>gender</th>
                <th>age</th>
                <th>department</th>
            </tr>
        </thead>
        <tbody>
            {% for row in queryset %}
                <tr>
                    <td>{{ row.id }}</td>
                    <td>{{ row.username }}</td>
                    <td>{{ row.get_gender_display }}</td>
                    <td>{{ row.age }}</td>
                    <td>{{ row.depart.title}}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

号码管理平台_django_验证码_12

在urls.py 中写相关的视图函数和url 的映射关系

from django.urls import path
from number_management.views import account, admin

urlpatterns = [
    path("admin/add/", admin.admin_add, name="admin_add")
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

在app/views/admin.py 中写 admin_add 视图函数

from django import forms

class AdminModelForm(forms.ModelForm):
    class Meta:
        model = models.Admin
        fields = ["username", "password", "age", "gender", "depart"]


def admin_add(request):
    form = AdminModelForm()
    return render(request, "admin_add.html", {"form": form})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

admin_add.html

{% extends "layout.html" %}

{% block content %}
    <form action="" method="post">
        {% csrf_token %}

        {% for field in form %}
            <p>{{ field.label }}: {{ field }} <span style="color:red">{{ field.errors.0 }}</span></p>
        {% endfor %}
        <input type="submit" value="提交">
    </form>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

号码管理平台_django_django_13

如上图, 使用 modelform, 和相关的model 有联系,给部门model 设置__str__,显示 __str__ 中的内容。显示每个对象的title

和choice 相关的字段不设置 默认 初始会显示一系列的横杆,设置 default, 显示设置的默认值,如上图,设置default= 1, 默认显示1

admin_add效果图

号码管理平台_django_bootstrap_14

11.表单的展示

上面的表单不好看, 利用 bootstrp 中的模版,展示一个好看的表单。

面板中套了一个 form 表单(bootstrap 上的模版)

{% extends "layout.html" %}

{% block content %}
    <div class="panel panel-default">
      <div class="panel-heading"><span class="glyphicon glyphicon-indent-left" aria-hidden="true"></span>表单操作</div>
      <div class="panel-body">
          <form class="form-horizontal">
              {% csrf_token %}
              {% for field in form %}
                  <div class="form-group">
                      <label for="inputEmail3" class="col-sm-2 control-label">{{ field.label }}</label>
                      <div class="col-sm-10">
                          {{ field }}
                          <span style="color:red">{{ field.errors.0 }}</span>
                      </div>
                </div>
              {% endfor %}

              <div class="form-group">
                  <div class="col-sm-offset-2 col-sm-10">
                      <button type="submit" class="btn btn-primary">保 存</button>
                  </div>
              </div>
          </form>
      </div>
    </div>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

号码管理平台_django_bootstrap_15

还是不好看,可以给添加一个 form-control, 可以 使用两种方式

app\views\admin.py

from django.shortcuts import render
from number_management import models
from django import forms


def admin_list(request):
    """
    用户列表
    :param request:
    :return:
    """
    # [obj, obj, obj]  order_by("-id")  根据id 倒序排序
    queryset = models.Admin.objects.all().order_by("-id")
    # for row in queryset:
        # 如果 models.py 该字段中定义了 choice 对应关系, 使用对象.get_字段名_display() 获取 choice 中设置的
        # 对应的值 例如 row.get_gender_dispaly 可以获取 男或者 女
        # choices=[(1, "男"), (2, "女")]

        # row.depart.title , 跨表查询
        # print(row.username, row.password, row.gender, row.get_gender_display(),row.depart.title)
        # mpx 8fe4282d77a078f5a064fff057288ee9 1 男 IT

    return render(request,"admin_list.html", {"queryset": queryset})


class AdminModelForm(forms.ModelForm):
    class Meta:
        model = models.Admin
        fields = ["username", "password", "age", "gender", "depart"]
        # 给表单增加样式, 字段比较多,加起来有点麻烦
        # widgets ={
        #     'username': forms.TextInput(attrs={"class": "form-control"})
        # }

    # 如果类中没有 __init__ 方法,执行父类中的__init__ 方法, 如果有就执行自己的__init__ 方法
    def __init__(self, *args, **kwargs):
        # 先执行一下父类的init 方法
        super().__init__(*args, **kwargs)

        # 自定义一些操作, 找到所有的字段
        print("----")
        print(self.fields)
        for name, field_object in self.fields.items():
            print(name, field_object)
            field_object.widget.attrs = {"class": "form-control"}


def admin_add(request):
    form = AdminModelForm()
    return render(request, "admin_add.html", {"form": form})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.

号码管理平台_django_验证码_16

输入框占一整行也不太好看, 给每个 输入框加一个 row, row 具有统一的边距, 每个form_group, 放到一个div 中,占 整行的6份, 一共12份, 给div 加一个 class="col-xs-6"

{% extends "layout.html" %}

{% block content %}
    <div class="panel panel-default">
      <div class="panel-heading"><span class="glyphicon glyphicon-indent-left" aria-hidden="true"></span>表单操作</div>
      <div class="panel-body">
          <form class="form-horizontal">
              {% csrf_token %}
              <div class="row">
                 {% for field in form %}
                     <div class="col-xs-6">
                         <div class="form-group">
                      <label for="inputEmail3" class="col-sm-2 control-label">{{ field.label }}</label>
                      <div class="col-sm-10">
                          {{ field }}
                          <span style="color:red">{{ field.errors.0 }}</span>
                      </div>
                </div>
                     </div>
                 {% endfor %}
              </div>
              <div class="row">
                  <div class="form-group">
                  <div class="col-xs-6">
                      <div class="col-sm-offset-2 col-sm-10">
                      <button type="submit" class="btn btn-primary">保 存</button>
                  </div>
                  </div>
              </div>
              </div>
          </form>
      </div>
    </div>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

号码管理平台_django_bootstrap_17

展示错误信息的时候,会把标签挤到下一个位置, 使用 positon:relative 和 position: absolute

相对定位

号码管理平台_django_django_18

{% extends "layout.html" %}

{% block content %}
    <div class="panel panel-default">
      <div class="panel-heading"><span class="glyphicon glyphicon-indent-left" aria-hidden="true"></span>表单操作</div>
      <div class="panel-body">
          <form class="form-horizontal">
              {% csrf_token %}
              <div class="row">
                 {% for field in form %}
                     <div class="col-xs-6">
                         <!-- 加一个底部边距可以使 错误信息离输入框远一点-->
                         <div class="form-group" style="margin-bottom:25px;">
                             <label class="col-sm-2 control-label">{{ field.label }}</label>
                             <div class="col-sm-10" style="position:relative">
                                 {{ field }}
                          <span style="color:red; position:absolute">{{ field.errors.0 }}</span>
                      </div>
                </div>
                     </div>
                 {% endfor %}
              </div>
              <div class="row">
                  <div class="form-group">
                  <div class="col-xs-6">
                      <div class="col-sm-offset-2 col-sm-10">
                      <button type="submit" class="btn btn-primary">保 存</button>
                  </div>
                  </div>
              </div>
              </div>
          </form>
      </div>
    </div>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

12.新建用户成功

号码管理平台_django_django_19

form 表单指定提交方式为 post 方式 admin_add.html

{% extends "layout.html" %}

{% block content %}
    <div class="panel panel-default">
      <div class="panel-heading"><span class="glyphicon glyphicon-indent-left" aria-hidden="true"></span>表单操作</div>
      <div class="panel-body">
          <form class="form-horizontal" method="post" novalidate>
              {% csrf_token %}
              <div class="row">
                 {% for field in form %}
                     <div class="col-xs-6">
                         <div class="form-group" style="margin-bottom:25px;">
                             <label class="col-sm-2 control-label">{{ field.label }}</label>
                             <div class="col-sm-10" style="position:relative">
                                 {{ field }}
                          <span style="color:red; position:absolute">{{ field.errors.0 }}</span>
                      </div>
                </div>
                     </div>
                 {% endfor %}
              </div>
              <div class="row">
                  <div class="form-group">
                  <div class="col-xs-6">
                      <div class="col-sm-offset-2 col-sm-10">
                      <button type="submit" class="btn btn-primary">保 存</button>
                  </div>
                  </div>
              </div>
              </div>
          </form>
      </div>
    </div>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

用户添加视图函数完成

app/views/admin.py

from django.shortcuts import render, redirect
from django import forms

from number_management import models
from utils.encrypt import md5

def admin_add(request):
    if request.method == "GET":
        form = AdminModelForm()
        return render(request, "admin_add.html", {"form": form})
    form = AdminModelForm(data=request.POST)
    if not form.is_valid():
        return render(request, "admin_add.html", {"form": form})

    # 读取密码并更新成md5 加密的新值
    form.instance.password = md5(form.instance.password)

    # 保存到数据库
    form.save()
    return redirect("/admin/list/")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

13.编辑用户

admin_list.html 每一行的数据后面加一个 编辑a标签,点击这个标签,跳转到 admin_edit.html

admin_add.html 和 admin_edit.html 页面的效果是一样的, 可以将 admin_add.html 更改成 admin_form.html, admin_add 和 admin_edit 操作都使用这个页面。

编辑的时候,只能编辑 密码以外的信息, 这个时候, 可以 把 adminModelForm 复制一份,删除其中的

password 字段

class AdminEditModelForm(forms.ModelForm):
    class Meta:
        model = models.Admin
        fields = ["username","age", "gender", "depart"]
        # 给表单增加样式, 字段比较多,加起来有点麻烦
        # widgets ={
        #     'username': forms.TextInput(attrs={"class": "form-control"})
        # }

    # 如果类中没有 __init__ 方法,执行父类中的__init__ 方法, 如果有就执行自己的__init__ 方法
    def __init__(self, *args, **kwargs):
        # 先执行一下父类的init 方法
        super().__init__(*args, **kwargs)

        # 自定义一些操作, 找到所有的字段
        print("----")
        print(self.fields)
        for name, field_object in self.fields.items():
            print(name, field_object)
            field_object.widget.attrs = {"class": "form-control"}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

编辑页面应该有默认值, admin_edit 视图函数是和 参数拼接到路径中的 url 对应的, 点击 admin_list 相关行的编辑a标签时,会把相关的 用户 id 传递给视图函数, 使用这个 id, 可以从数据库中查找到相关的信息,使用

# 编辑之前应该有默认值
    admin_object = models.Admin.objects.filter(id=aid).first()
    form = AdminEditModelForm(instance=admin_object)
  • 1.
  • 2.
  • 3.

如上两行指定 form 表单的默认值

from django.contrib import admin
from django.urls import path
from number_management.views import account, admin

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("login/", account.login, name="login"),
    path("logout/", account.logout, name="logout"),
    path("img/code/", account.img_code, name="img_code"),
    path("home", account.home, name="home"),

    path("admin/list/", admin.admin_list, name="admin_list"),
    path("admin/add/", admin.admin_add, name="admin_add"),
    
    // 参数拼接到路径中
    path("admin/edit/<int:aid>/", admin.admin_edit, name="admin_edit")
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

编辑视图函数 app/views/admin.py 中

def admin_edit(request, aid):
    # 编辑之前应该有默认值
    admin_object = models.Admin.objects.filter(id=aid).first()
    if request.method == "GET":
        form = AdminEditModelForm(instance=admin_object)
        return render(request, "admin_form.html", {"form": form})
    form = AdminEditModelForm(instance=admin_object, data=request.POST)
    if not form.is_valid():
        return render(request, 'admin_form.html', {"form":form})

    # 更新
    form.save()
    return redirect("/admin/list/")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

14.删除用户

删除时,使用bootstrap 中的 模态框,点击删除弹出一个模态框, 确认是否删除

号码管理平台_django_django_20

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
        <h4 class="modal-title" id="myModalLabel">Modal title</h4>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

号码管理平台_django_django_21

删除时比较危险的操作, 可以使用 警告框的样式。

号码管理平台_django_bootstrap_22

检查-->定位-->copy 样式,

号码管理平台_django_bootstrap_23

<!--使用 class 中的内容  class="alert alert-danger alert-dismissible fade in" -->

<div class="alert alert-danger alert-dismissible fade in" role="alert">
      <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
      <h4>Oh snap! You got an error!</h4>
      <p>Change this and that and try again. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum.</p>
      <p>
        <button type="button" class="btn btn-danger">Take this action</button>
        <button type="button" class="btn btn-default">Or do this</button>
      </p>
    </div>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

admin_list.html

{% extends "layout.html" %}


{% block content %}

    <div style="margin-bottom:10px">
        <a class="btn btn-success" href="/admin/add/">
            <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>新建用户</a>
    </div>
    <table class="table table-bordered">
        <thead>
        <tr>
            <th>ID</th>
            <th>name</th>
            <th>gender</th>
            <th>age</th>
            <th>department</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        {% for row in queryset %}
            <tr>
                <td>{{ row.id }}</td>
                <td>{{ row.username }}</td>
                <td>{{ row.get_gender_display }}</td>
                <td>{{ row.age }}</td>
                <td>{{ row.depart.title }}</td>
                <td>
                    <a class="btn btn-primary btn-xs" href="/admin/edit/{{ row.id }}/">
                        <!--图标-->
                        {#                            <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>#}
                        编辑
                    </a>
                    <input type="button" value="删除" class="btn btn-danger btn-xs" data-toggle="modal"
                           data-target="#myModal">
                </td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

    <!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">

            <div class="alert alert-danger alert-dismissible fade in" role="alert">
                <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
                        aria-hidden="true">×</span></button>
                <h4>Oh snap! You got an error!</h4>
                <p>Change this and that and try again. Duis mollis, est non commodo luctus, nisi erat porttitor
                    ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum.</p>
                <p>
                    <button type="button" class="btn btn-danger">Take this action</button>
                    <button type="button" class="btn btn-default">Or do this</button>
                </p>
            </div>
        </div>
    </div>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.

号码管理平台_django_验证码_24

{% extends "layout.html" %}


{% block content %}

    <div style="margin-bottom:10px">
        <a class="btn btn-success" href="/admin/add/">
            <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>新建用户</a>
    </div>
    <table class="table table-bordered">
        <thead>
        <tr>
            <th>ID</th>
            <th>name</th>
            <th>gender</th>
            <th>age</th>
            <th>department</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        {% for row in queryset %}
            <tr>
                <td>{{ row.id }}</td>
                <td>{{ row.username }}</td>
                <td>{{ row.get_gender_display }}</td>
                <td>{{ row.age }}</td>
                <td>{{ row.depart.title }}</td>
                <td>
                    <a class="btn btn-primary btn-xs" href="/admin/edit/{{ row.id }}/">
                        <!--图标-->
                        {#                            <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>#}
                        编辑
                    </a>
                    <input type="button" value="删除" class="btn btn-danger btn-xs" data-toggle="modal"
                           data-target="#myModal">
                </td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

    <!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">

            <div class="alert alert-danger alert-dismissible fade in" role="alert">
                <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
                        aria-hidden="true">×</span></button>
                <h4>是否确认删除?</h4>
                <p style="margin: 20px 0;">删除后,与之关联的所有相关的数据都会被删除调,确认是否继续?</p>
                <p>
                    <button type="button" class="btn btn-danger">确 认</button>
                    <button type="button" class="btn btn-default">取 消</button>
                </p>
            </div>
        </div>
    </div>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.

号码管理平台_django_bootstrap_25

点击删除按钮, 获取到需要删除的行数据,给按钮绑定相应的点击事件,点击事件触发 模态框弹出

模态框的弹出,可以使用 类属性的方式,也可以使用 javascript 调用的方式

号码管理平台_django_django_26

点击 删除按钮,设置,全局删除ID 为 需要删除的 id ,同时弹出模态框

点击 模态框中的确认时, 将需要删除的id 传递给后端的视图函数, 删除数据,重定向到 admin_list.html 页面

点击模态框中的 取消按钮时, 将模态框设置隐藏。

需要给 模态框中的 两个按钮(确认和取消, 绑定 onclick 事件)

{% block js %}
    <script>
        // 当前删除的 id
        DELETE_ID = 0;
        function deleteAction(id){
            DELETE_ID = id;
            console.log(id);
            $("#myModel").modal("show");
        }
        
    </script>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
{% block js %}
    <script>
        // 当前删除的 id
        DELETE_ID = 0;
        function deleteAction(id){
            DELETE_ID = id;
            console.log(id);
            $("#myModal").modal("show");
        }
        // 确认删除
        function confirmDelete(){
            // 向后端发送请求,  DELETE_ID -> 删除
            // 页面刷新
        }

        //取消删除
        function cancelDelete(){
            // 全局变量重置成0, 模态框设置隐藏
            DELETE_ID = 0;
            $("#myModal").modal("hide");
        }

    </script>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

向后端发送请求的方式,

- 点击 a标签, 拼接参数的方式
- post 请求, submit 提交的时候
  • 1.
  • 2.

上面这两种,发送请求的时候, 后刷新页面

ajax 发送请求发送请求的时候, 不会刷新页面

号码管理平台_django_django_27

点击模态框的中的确认删除 按钮时, 向后端发送 ajax 请求。

号码管理平台_django_django_28

{% block js %}
    <script>
        // 当前删除的 id
        DELETE_ID = 0;
        function deleteAction(id){
            DELETE_ID = id;
            console.log(id);
            $("#myModal").modal("show");
        }
        // 确认删除
        function confirmDelete(){
            // 向后端发送请求,  DELETE_ID -> 删除
            // 页面刷新
            // admin/delete?aid=1
            $.ajax({
                url:"admin/delete/",
                type:"GET",
                data:{
                    aid:DELETE_ID
                },
                success:function(res){
                    console.log("请求返回值:", res);
            }
            })
        }

        //取消删除
        function cancelDelete(){
            // 全局变量重置成0, 模态框设置隐藏
            DELETE_ID = 0;
            $("#myModal").modal("hide");
        }

    </script>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

urls.py 中的 url 和视图函数的对应关系

from django.contrib import admin
from django.urls import path
from number_management.views import account, admin

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("login/", account.login, name="login"),
    path("logout/", account.logout, name="logout"),
    path("img/code/", account.img_code, name="img_code"),
    path("home", account.home, name="home"),

    path("admin/list/", admin.admin_list, name="admin_list"),
    path("admin/add/", admin.admin_add, name="admin_add"),
    path("admin/edit/<int:aid>/", admin.admin_edit, name="admin_edit"),
    
    # 新增的 url
    path("admin/delete/<int:aid>/", admin.admin_delete, name="admin_delete")
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

app/views/admin.py 中的 admin_delete 视图函数

from django.shortcuts import render, redirect, HttpResponse
from django import forms
from django.http import JsonResponse

from number_management import models
from utils.encrypt import md5

def admin_delete(request):
    aid = request.GET.get("aid")
    print("要删除的ID:", aid)
    models.Admin.objects.filter(id=aid).delete()
    # return HttpResponse("11")
    return JsonResponse({"status": True})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

admin_list.html

{% extends "layout.html" %}


{% block content %}

    <div style="margin-bottom:10px">
        <a class="btn btn-success" href="/admin/add/">
            <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>新建用户</a>
    </div>
    <table class="table table-bordered">
        <thead>
        <tr>
            <th>ID</th>
            <th>name</th>
            <th>gender</th>
            <th>age</th>
            <th>department</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        {% for row in queryset %}
            <tr>
                <td>{{ row.id }}</td>
                <td>{{ row.username }}</td>
                <td>{{ row.get_gender_display }}</td>
                <td>{{ row.age }}</td>
                <td>{{ row.depart.title }}</td>
                <td>
                    <a class="btn btn-primary btn-xs" href="/admin/edit/{{ row.id }}/">
                        <!--图标-->
                        {#                            <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>#}
                        编辑
                    </a>
                    <input type="button" value="删除" class="btn btn-danger btn-xs" onclick="deleteAction({{ row.id }});">
                </td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

    <!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">

            <div class="alert alert-danger alert-dismissible fade in" role="alert">
                <button type="button" class="close" data-dismiss="alert" aria-label="Close"></button>
                <h4>是否确认删除?</h4>
                <p style="margin: 20px 0;">删除后,与之关联的所有相关的数据都会被删除调,确认是否继续?</p>
                <p>
                    <button type="button" class="btn btn-danger" onclick="confirmDelete()">确 认</button>
                    <button type="button" class="btn btn-default" onclick="cancelDelete()">取 消</button>
                </p>
            </div>
        </div>
    </div>
{% endblock %}

{% block js %}
    <script>
        // 当前删除的 id
        DELETE_ID = 0;
        function deleteAction(id){
            DELETE_ID = id;
            console.log(id);
            $("#myModal").modal("show");
        }
        // 确认删除
        function confirmDelete(){
            // 向后端发送请求,  DELETE_ID -> 删除
            // 页面刷新
            // admin/delete?aid=1
            $.ajax({
                url:"/admin/delete/",
                type:"GET",
                data:{
                    aid:DELETE_ID
                },
                dataType: "JSON",
                success:function(res){
                    if(res.status){
                        // 删除成功,刷新页面
                        location.reload();
                    }else{
                        alert(res.error);
                    }
                    console.log("请求返回值:", res);
            }
            })
        }

        //取消删除
        function cancelDelete(){
            // 全局变量重置成0, 模态框设置隐藏
            DELETE_ID = 0;
            $("#myModal").modal("hide");
        }

    </script>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.

15.号码管理平台实现思路

参考 用户管理实现

  • 号码列表展示
    点击导航条上的号码管理a 标签访问 号码管理的 url 和视图函数 ,在视图函数中从数据库中查询所有的号码展示到 号码管理页面
<ul class="nav navbar-nav">
        <li><a href="/admin/list/">用户管理</a></li>
        <li><a href="/number/list/">号码管理</a></li>
      </ul>
  • 1.
  • 2.
  • 3.
  • 4.

url 和视图的映射关系

from django.contrib import admin
from django.urls import path
from number_management.views import account, admin, number

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("login/", account.login, name="login"),
    path("logout/", account.logout, name="logout"),
    path("img/code/", account.img_code, name="img_code"),
    path("home", account.home, name="home"),

    path("admin/list/", admin.admin_list, name="admin_list"),
    path("admin/add/", admin.admin_add, name="admin_add"),
    path("admin/edit/<int:aid>/", admin.admin_edit, name="admin_edit"),
    path("admin/delete/", admin.admin_delete, name="admin_delete"),
	
    # 新增的 url
    path("number/list", number.number_list, name="number_list")
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

在 app/views/文件夹下创建一个 number.py 用来存放 number 相关的视图函数

from django.shortcuts import render
from number_management import models


def number_list(request):
    query_set = models.Phone.objects.all().order_by("-id")
    return render(request, "number_list.html", {"query_set": query_set})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

参考 admin_list.html 书写 number_list.html

面板中的 号码展示,

新增号码按钮, 点击访问 url /number/add

编辑号码按钮, 点击访问url /number/edit

删除号码按钮, 点击删除,使用 jquery 绑定事件弹出 模态框,点击模态框中的确认按钮,向 url number/delete 发送ajax 请求(页面不刷新)传递 需要删除的数据行的 id, 删除对应的号码

点击模态框中的取消按钮,使用 jquery 绑定事件,隐藏模态框的展示

# urls.py
from django.urls import path
from number_management.views import account, admin, number

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("login/", account.login, name="login"),
    path("logout/", account.logout, name="logout"),
    path("img/code/", account.img_code, name="img_code"),
    path("home", account.home, name="home"),

    path("admin/list/", admin.admin_list, name="admin_list"),
    path("admin/add/", admin.admin_add, name="admin_add"),
    path("admin/edit/<int:aid>/", admin.admin_edit, name="admin_edit"),
    path("admin/delete/", admin.admin_delete, name="admin_delete"),

    path("number/list/", number.number_list, name="number_list"),
    path("number/add/", number.number_add, name="number_add"),
    path("number/edit/<int:aid>/", number.number_edit, name="number_edit"),
    path("number/delete/", number.number_delete, name="number_delete")
]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

app/views/number.py

from django import forms
from django.shortcuts import render, redirect
from django.http import JsonResponse
from number_management import models


class numberModelForm(forms.ModelForm):
    class Meta:
        model = models.Phone
        fields = ["mobile", "price", "level", "status", "admin"]
        # 给表单增加样式, 字段比较多,加起来有点麻烦
        # widgets ={
        #     'username': forms.TextInput(attrs={"class": "form-control"})
        # }

    # 如果类中没有 __init__ 方法,执行父类中的__init__ 方法, 如果有就执行自己的__init__ 方法
    def __init__(self, *args, **kwargs):
        # 先执行一下父类的init 方法
        super().__init__(*args, **kwargs)

        # 自定义一些操作, 找到所有的字段
        print("----")
        print(self.fields)
        for name, field_object in self.fields.items():
            print(name, field_object)
            field_object.widget.attrs = {"class": "form-control"}


def number_list(request):
    query_set = models.Phone.objects.all().order_by("-id")
    return render(request, "number_list.html", {"query_set": query_set})


def number_add(request):
    if request.method == "GET":
        form = numberModelForm()
        return render(request, "number_form.html", {"form": form})
    form = numberModelForm(request.POST)
    if not form.is_valid():
        return render(request, "number_form.html",{"form": form})

    # 保存到数据库
    form.save()
    return redirect("number_list")


def number_edit(request, aid):
    edit_object = models.Phone.objects.filter(id=aid).first()
    if request.method == "GET":
        form = numberModelForm(instance=edit_object)
        return render(request, "number_form.html", {"form": form})
    form = numberModelForm(instance=edit_object, data=request.POST)
    if not form.is_valid():
        return render(request, "number_form.html", {"form": form})

    form.save()
    return redirect("number_list")


def number_delete(request):
    aid = request.GET.get("aid")
    models.Phone.objects.filter(id=aid).delete()
    return JsonResponse({"status": True})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

number_form.html

{% extends "layout.html" %}

{% block content %}
    <div class="panel panel-default">
      <div class="panel-heading"><span class="glyphicon glyphicon-indent-left" aria-hidden="true"></span>表单操作</div>
      <div class="panel-body">
          <form class="form-horizontal" method="post" novalidate>
              {% csrf_token %}
              <div class="row">
                 {% for field in form %}
                     <div class="col-xs-6">
                         <div class="form-group" style="margin-bottom:25px;">
                             <label class="col-sm-2 control-label">{{ field.label }}</label>
                             <div class="col-sm-10" style="position:relative">
                                 {{ field }}
                          <span style="color:red; position:absolute">{{ field.errors.0 }}</span>
                      </div>
                </div>
                     </div>
                 {% endfor %}
              </div>
              <div class="row">
                  <div class="form-group">
                  <div class="col-xs-6">
                      <div class="col-sm-offset-2 col-sm-10">
                      <button type="submit" class="btn btn-primary">保 存</button>
                  </div>
                  </div>
              </div>
              </div>
          </form>
      </div>
    </div>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

number_list.html

{% extends "layout.html" %}


{% block content %}

    <div style="margin-bottom:10px">
        <a class="btn btn-success" href="/number/add/">
            <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>新建号码</a>
    </div>
    <table class="table table-bordered">
        <thead>
        <tr>
            <th>ID</th>
            <th>Phone</th>
            <th>Price</th>
            <th>Level</th>
            <th>status</th>
            <th>admin</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        {% for row in query_set %}
            <tr>
                <td>{{ row.id }}</td>
                <td>{{ row.mobile }}</td>
                <td>{{ row.price }}</td>
                <td>{{ row.get_level_display }}</td>
                <td>{{ row.get_status_display }}</td>
                <td>{{ row.admin.username }}</td>
                <td>
                    <a class="btn btn-primary btn-xs" href="/number/edit/{{ row.id }}/">
                        <!--图标-->
                        {#                            <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>#}
                        编辑
                    </a>
                    <input type="button" value="删除" class="btn btn-danger btn-xs" onclick="deleteAction({{ row.id }});">
                </td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

    <!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">

            <div class="alert alert-danger alert-dismissible fade in" role="alert">
                <button type="button" class="close" data-dismiss="alert" aria-label="Close"></button>
                <h4>是否确认删除?</h4>
                <p style="margin: 20px 0;">删除后,与之关联的所有相关的数据都会被删除调,确认是否继续?</p>
                <p>
                    <button type="button" class="btn btn-danger" onclick="confirmDelete()">确 认</button>
                    <button type="button" class="btn btn-default" onclick="cancelDelete()">取 消</button>
                </p>
            </div>
        </div>
    </div>
{% endblock %}

{% block js %}
    <script>
        // 当前删除的 id
        DELETE_ID = 0;
        function deleteAction(id){
            DELETE_ID = id;
            console.log(id);
            $("#myModal").modal("show");
        }
        // 确认删除
        function confirmDelete(){
            // 向后端发送请求,  DELETE_ID -> 删除
            // 页面刷新
            // admin/delete?aid=1
            $.ajax({
                url:"/number/delete/",
                type:"GET",
                data:{
                    aid:DELETE_ID
                },
                dataType: "JSON",
                success:function(res){
                    if(res.status){
                        // 删除成功,刷新页面
                        location.reload();
                    }else{
                        alert(res.error);
                    }
                    console.log("请求返回值:", res);
            }
            })
        }

        //取消删除
        function cancelDelete(){
            // 全局变量重置成0, 模态框设置隐藏
            DELETE_ID = 0;
            $("#myModal").modal("hide");
        }

    </script>
{% endblock %}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.

16.总结

号码管理平台_django_验证码_29

号码管理平台_django_验证码_30

项目代码地址:  https://github.com/Red-brief/phone_management_platform/tree/main