当前位置:   article > 正文

【前端开发学习】7.Django_django 前端

django 前端

1 初识Django

1.1 django的安装

pip install django
  • 1

1.2 创建django项目

  • cmd命令行创建
# 已经进行了环境变量配置
django-admin.exe startproject 项目名称
  • 1
  • 2
  • Pycharm 【需要专业版】

1.3 两种创建方式的对比

  • 命令行,创建的项目是比较标准的;
  • Pycharm,与命令行方式对比:
    • 增加了templates目录;【删除】
    • setting.py中,TEMPLATES = [{ ‘DIRS’: [’ ******* ']}] 【DIRS中的内容删除】

1.4 默认文件介绍

mysite

  • manage.py 【项目管理,启动项目、创建APP、数据管理】- 不修改,常用
  • mysite
    • __ init __.py
    • settings.py 【项目配置文件】- 常常操作
    • urls.py 【URL和函数的对应关系】- 常常操作
    • asgi.py 【接收网络请求「异步式」】- 不修改
    • wsgi.py 【接收网络请求「同步式」】- 不修改

1.5 APP的创建和说明

1. APP 的例子

  • 项目

    • app,用户管理 【表结构、函数、HTML模板、CSS】
    • app,订单管理 【表结构、函数、HTML模板、CSS】
    • app,后台管理 【表结构、函数、HTML模板、CSS】
    • app,网站 【表结构、函数、HTML模板、CSS】
    • app,API 【表结构、函数、HTML模板、CSS】

    注意,我们开发比较简洁,用不到多 APP ,通常情况下,项目创建一个 APP 即可。

2. 创建 APP,在终端输入:

python manage.py startapp app01
  • 1

3. APP 默认文件介绍

  • app01
    • __ init __.py
    • admin.py【固定,不用动】 django默认提供了admin后台管理
    • apps.py 【固定,不用动】 app启动类
    • migrations 【固定,不用动】 数据库字段变更记录
      • __ init __.py
    • models.py重要】 对数据库进行操作
    • tests.py【固定,不用动】 单元测试
    • views.py重要】 函数

1.6 启动运行django

1. 注册 app 【setting.py】

在这里插入图片描述

2. 编写 URL 和视图函数的对应关系 【urls.py】

在这里插入图片描述

3. 编写视图函数 【views.py】

在这里插入图片描述

4. 启动 Django 项目

命令行启动

python manage.py runserver
  • 1

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

1.7 模板和静态文件

1. templates 模板

在这里插入图片描述
在这里插入图片描述

2. 静态文件

在开发过程中,一般将 「图片、CSS、js」都会当作静态文件处理。

(1)在 app 目录下创建static文件夹

在这里插入图片描述

(2)引用静态文件
在这里插入图片描述

1.8 模板语法

1. 本质:在 HTML 中写一些占位符,由数据对这些占位符进行替换和处理。
在这里插入图片描述

2. 案例:伪联通新闻中心

(1)在 urls.py 创建函数的对应关系

在这里插入图片描述

(2)在 views 中编写函数

在这里插入图片描述

(3)在 templates 的 news.html 编写模板语法

在这里插入图片描述

(4)页面展示

在这里插入图片描述

1.9 请求和响应

1.

在这里插入图片描述

2. 案例:用户登录

(1)发生如下错误,只需要在 form 表单中伪造跨站请求 {% csrf_token %} 。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

(2)最终代码:

在这里插入图片描述

(3)效果展示

在这里插入图片描述

在这里插入图片描述

1.10 orm数据库操作

ORM

  • 创建、修改、删除数据库中的表;(不用写SQL语句)【无法创建数据库】
  • 操作表中的数据(不用写SQL语句)。

在这里插入图片描述

1. 安装第三方库

pip install mysqlclient==1.4.1
  • 1

2. 创建数据库

  • 首先在终端启动 mysql:
net start mysql
  • 1
  • 登录 mysql(已经将初始密码设为 0 )
mysql -u root -p
  • 1
  • 创建数据库(其中 gx 是数据库名称):
create database gx DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
  • 1

3. django 连接数据库

在 settings.py 文件中进行配置和修改。

更改默认 DATABASES :

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # 引擎
        'NAME': 'gx', # 数据库名字
        'USER': 'root', # 用户名
        'PASSWORD': '123456', # 密码
        'HOST': '127.0.0.1', # 哪台机器安装了MySQL - 本机
        'PORT': '3306',
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4. django 创建表

(1)在 models.py 文件中:

在这里插入图片描述

等同于:

create table app01_userinfo(
    id bigint auto_increment primary key, # django自动添加
    name varchar(32),
    password varchar(64),
    age int
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(2)在 pycharm 终端输入,注意, app 需要提前注册:

python manage.py makemigrations
python manage.py migrate
  • 1
  • 2

在这里插入图片描述

至此,表已经创建成功。

在这里插入图片描述
在这里插入图片描述

5. django 修改表

(1) 删除某个列:

  • 注释该列;
  • 在 pycharm 终端输入:
python manage.py makemigrations
python manage.py migrate
  • 1
  • 2

(2)添加某个列:
- 在 python 代码中输入该列;
- 在 pycharm 终端输入:

python manage.py makemigrations
python manage.py migrate
  • 1
  • 2

(3)但是,对于 添加列 需要注意,由于已存在的列可能已有数据,所以新增列必须要指定对应的数据:

  • 选择 1,手动输入一个值;
  • 选择 2,回到代码设置默认值;
age = models.IntegerField(default=2)
  • 1
  • 允许为空;
data = models.IntegerField(null=True, blank=True)
  • 1

总结:对表结构进行调整

  • 在 models.py 文件中进行操作类;
  • 输入命令:
    python manage.py makemigrations
    python manage.py migrate

6. 操作表中的数据

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1.11 ORM 数据库案例:用户管理

1. 展示用户列表

  • url;
  • 函数
    • 获取所有用户信息;
    • HTML 渲染;

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2. 添加用户

  • url;
  • 函数
    • GET,看到页面,输入内容;
    • POST,提交,写入到数据库。

(1)在 urls.py 中添加 path:

在这里插入图片描述

(2)编写函数 info_add :

在这里插入图片描述

(3)编写 info_add.html ,注意要有 {% csrf_token %} ,使得跨站网址请求能够成功。

在这里插入图片描述
(4)效果展示

在这里插入图片描述在这里插入图片描述

3. 删除用户

  • url;
  • 函数

(1)在 urls.py 添加 path:

在这里插入图片描述

(2) 在 views.py 中编写相关代码:

在这里插入图片描述

(3)结果展示:(当然在 /info/list.html 中也做了修改)

在这里插入图片描述

2 案例

2.1 创建项目和 APP

  1. 在终端进入项目的存储路径,然后创建项目:

    E:\PycharmProjects>django-admin.exe startproject day16
    
    • 1
  2. 创建APP:

    E:\PycharmProjects\day16>python manage.py startapp app01
    
    • 1
  3. 注册 APP ,修改 setting.py :

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01.apps.App01Config',
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

2.2 表结构的创建

在这里插入图片描述

models.py

from django.db import models

# Create your models here.

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

class UserInfo(models.Model):
    """员工表"""
    name = models.CharField(verbose_name="姓名", max_length=16)
    password = models.CharField(verbose_name="密码", max_length=64)
    age = models.IntegerField(verbose_name="年龄")
    account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
    create_time = models.DateTimeField(verbose_name="入职时间")

    # 1. 有约束
    # - to,与哪张表关联
    # - to_field,表中的哪一列关联
    # 2. django自动
    # - 写的 depart
    # - 实际生成 depart_id
    # 3. 部门表被删除
    # 3.1 级联删除
    depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
    # 3.2 置空
    # depart = models.ForeignKey(to="Department", to_field="id", null=True, blank=True, on_delete=models.SET_NULL)
    gender_choices = (
        (1, "男"),
        (2, "女"),
    )
    gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)
  • 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

2.3 生成数据库

  1. cmd 终端创建数据库
create database day16 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
  • 1
  1. 在 setting.py 中修改 DATABASES
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # 引擎
        'NAME': 'day16', # 数据库名字
        'USER': 'root', # 用户名
        'PASSWORD': 'root', # 密码
        'HOST': '127.0.0.1', # 哪台机器安装了MySQL - 本机
        'PORT': '3306',
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. django 命令生成表
python manage.py makemigrations
python manage.py migrate
  • 1
  • 2

表结构创建成功:
在这里插入图片描述

2.4 部门管理

在这里插入图片描述
depart_list.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/css/bootstrap.min.css' %}">
</head>
<body>
<nav class="navbar navbar-default">
    <div class="container">
        <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>

        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li><a href="depart/list">部门管理</a></li>
                <li><a href="#">用户管理</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">登录</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">rice <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">个人资料</a></li>
                        <li><a href="#">用户信息</a></li>
                        <li><a href="#">注销</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>
<div>
    <div class="container">
        <div style="margin-bottom: 10px">
            <a class="btn btn-success" href="#">新建部门</a>
        </div>
        <div class="panel panel-default">
            <div class="panel-heading">
                <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
                部门列表
            </div>
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>部门名称</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                <tr>
                    <td>1</td>
                    <td>销售部</td>
                    <td>
                        <a class="btn btn-primary btn-xs">编辑</a>
                        <a class="btn btn-danger btn-xs">删除</a>
                    </td>
                </tr>
                </tbody>
            </table>

        </div>

    </div>
</div>
</div>
<script src="{% static 'jquery/jquery.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</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
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

2.5 数据库数据

在这里插入图片描述

views.py

from django.shortcuts import render
from app01 import models
# Create your views here.

def depart_list(request):
    """部门列表"""

    # 去数据库中获取所有部门列表
    # [对象, 对象, 对象]
    queryset = models.Department.objects.all()

    return render(request, 'depart_list.html', {'queryset': queryset})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

depart_list.html

                <tbody>
                {% for obj in queryset %}
                <tr>
                    <td>{{ obj.id }}</td>
                    <td>{{ obj.title }}</td>
                    <td>
                        <a class="btn btn-primary btn-xs">编辑</a>
                        <a class="btn btn-danger btn-xs">删除</a>
                    </td>
                </tr>
                {% endfor %}
                </tbody>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.6 添加部门页面

在这里插入图片描述

views.py

def depart_add(request):
    """添加部门"""
    return render(request, 'depart_add.html')
  • 1
  • 2
  • 3

depart_list.html

<div style="margin-bottom: 10px">
    <a class="btn btn-success" href="/depart/add/" >新建部门</a>
</div>
  • 1
  • 2
  • 3

depart_add.html

<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">部门列表</h3>
        </div>
        <div class="panel-body">
            <form>
                <div class="form-group">
                    <label>标题</label>
                    <input type="text" class="form-control" placeholder="标题" name="title" />
                </div>
                <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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2.7 部门:添加

views.py

# 导入redirect
from django.shortcuts import render, redirect
  • 1
  • 2
def depart_add(request):
    """添加部门"""
    if request.method == "GET":
        return render(request, 'depart_add.html')

    # 获取用户POST提交过来的数据
    title = request.POST.get("title")

    # 保存到数据库
    models.Department.objects.create(title=title)

    # 重定向到部门列表
    return redirect('/depart/list')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

depart_add.html

        <div class="panel-body">
            <form method="post">
                {% csrf_token %}
                <div class="form-group">
                    <label>标题</label>
                    <input type="text" class="form-control" placeholder="标题" name="title"/>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">提交</button>
                </div>
            </form>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2.8 部门:删除

views.py

def depart_delete(request):
    """删除部门"""
    # 获取ID
    nid = request.GET.get('nid')

    # 删除
    models.Department.objects.filter(id=nid).delete()

    # 重定向回部门列表
    return redirect("/depart/list/")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

depart_list.html

<a class="btn btn-danger btn-xs" href="/depart/delete/?nid= {{ obj.id }}">删除</a>
  • 1

2.9 部门:编辑

在这里插入图片描述

urls.py

/< 正则表达式 >/

urlpatterns = [
    # http://127.0.0.1:8000/depart/1/edit/
    path('depart/<int:nid>/edit/', views.depart_edit),
]
  • 1
  • 2
  • 3
  • 4

views.py

def depart_edit(request, nid):
    """修改部门"""
    if(request.method == "GET"):
        # 根据nid 获取它的数据 [object,]
        row_object = models.Department.objects.filter(id=nid).first()
        return render(request, 'depart_edit.html', {"title": row_object.title})

    # 获取用户提交的数据
    title = request.POST.get("title")
    # 更新数据
    models.Department.objects.filter(id=nid).update(title=title)
    # 重定向回部门列表界面
    return redirect("/depart/list/")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

depart_edit.html

<input type="text" class="form-control" placeholder="标题" name="title" value="{{ title }}"/>
  • 1

2.10 模板继承

  1. 定义模板:

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/css/bootstrap.min.css' %}">
</head>
<body>
<div>
    {% block content %}
    {% endblock%}
</div>
<script src="{% static 'jquery/jquery.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  1. 在别的 html 界面继承模板:

children.html

{% extends 'layout.html' %}

{% block content %}

<!--新增内容-->

{% endblock %}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

当然, 也可以定义多个模板:

layout.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% block css %}
    {% endblock%}
</head>
<body>
<div>
    {% block content %}
    {% endblock%}
</div>
    {% block js %}
    {% endblock%}
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

children.html

{% extends 'layout.html' %}

{% block css %}
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
{% endblock%}

{% block content %}
<!--新增内容-->
{% endblock %}

{% block js %}
    <script src="{% static 'jquery/jquery.min.js' %}"></script>
{% endblock%}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.11 用户管理:列表

  1. 在 mysql 插入数据
    insert into app01_userinfo(name, password, age, account, create_time, gender, depart_id) values("rice", "123", 23, 100.68, "2020-01-11", 2, 1);
    
    insert into app01_userinfo(name, password, age, account, create_time, gender, depart_id) values("candy", "123", 26, 100.68, "2021-01-11", 1, 2);
    
    insert into app01_userinfo(name, password, age, account, create_time, gender, depart_id) values("romance", "123", 25, 100.68, "2020-01-11", 2, 4);
    
    • 1
    • 2
    • 3
    • 4
    • 5

  1. urls.py

    path('user/list/', views.user_list),
    
    • 1
  2. views.py

    def user_list(request):
        """用户管理"""
    
        # 获取所有用户信息
        queryset = models.UserInfo.objects.all()
        # python 写法
        # for obj in queryset:
        #     id = obj.id
        #     name = obj.name
        #     password = obj.password
        #     age = obj.age
        #     account = obj.account
        #     create_time = obj.create_time.strftime("%Y-%m-%d")
        #     gender = obj.get_gender_display()
        #     title = obj.depart.title # 根据id自动去关联的表中获取哪一行的数据depart对象
        return render(request, 'user_list.html', {"queryset": queryset})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    1. user_list.html
    <table class="table table-bordered">
        <thead>
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>密码</th>
            <th>年龄</th>
            <th>余额</th>
            <th>入职时间</th>
            <th>性别</th>
            <th>所属部门</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        {% for obj in queryset %}
        <tr>
            <td>{{ obj.id }}</td>
            <td>{{ obj.name }}</td>
            <td>{{ obj.password }}</td>
            <td>{{ obj.age }}</td>
            <td>{{ obj.account }}</td>
            <td>{{ obj.create_time|date:"Y-m-d" }}</td>
            <td>{{ obj.get_gender_display }}</td>
            <td>{{ obj.depart.title }}</td>
            <td>
                <a class="btn btn-primary btn-xs" href="#">编辑</a>
                <a class="btn btn-danger btn-xs" href="#">删除</a>
            </td>
        </tr>
        {% endfor %}
        </tbody>
    </table>
    
    • 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
  3. 效果展示

在这里插入图片描述

2.12 用户管理:添加

1. 思路

  • 原始方法:比较复杂,因此最终不采用;

    缺点

    • 用户提交数据没有校验;
    • 发生错误的时候,页面没有错误提示;
    • 页面上,每一个字段都需要我们重新写一遍;
    • 关联数据需要手动获取并通过循环才能展示在页面。
  • Django 组件

    • Form 组件 【简便】
    • ModelForm 组件 【最简便】【最推荐】

2. 原始方法

  1. views.py

    def user_add(request):
        """添加用户"""
        if request.method == "GET":
            context = {
                'gender_choices': models.UserInfo.gender_choices,
                'depart_list': models.Department.objects.all()
            }
            return render(request, 'user_add.html', context)
    
        # 获取用户提交的数据
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        age = request.POST.get('age')
        account = request.POST.get('ac')
        ctime = request.POST.get('ctime')
        gender = request.POST.get('gd')
        depart_id = request.POST.get('dp')
    
        # 添加到数据库中
        models.UserInfo.objects.create(name=user, password=pwd, age=age,
                                       account=account, create_time=ctime,
                                       gender=gender, depart_id=depart_id)
        # 返回到用户列表界面
        return redirect("/user/list")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  2. user_add.html

    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">用户列表</h3>
            </div>
            <div class="panel-body">
                <form method="post">
                    {% csrf_token %}
                    <div class="form-group">
                        <label>姓名</label>
                        <input type="text" class="form-control" placeholder="姓名" name="user"/>
                    </div>
                    <div class="form-group">
                        <label>密码</label>
                        <input type="text" class="form-control" placeholder="密码" name="pwd"/>
                    </div>
                    <div class="form-group">
                        <label>年龄</label>
                        <input type="text" class="form-control" placeholder="年龄" name="age"/>
                    </div>
                    <div class="form-group">
                        <label>余额</label>
                        <input type="text" class="form-control" placeholder="余额" name="ac"/>
                    </div>
                    <div class="form-group">
                        <label>入职时间</label>
                        <input type="text" class="form-control" placeholder="入职时间" name="ctime"/>
                    </div>
                    <div class="form-group">
                        <label>性别</label>
                        <select class="form-control" name="gd">
                            {% for gender in gender_choices %}
                            <option value="{{ gender.0 }}">{{ gender.1 }}</option>
                            {% endfor %}
                        </select>
                    </div>
                    <div class="form-group">
                        <label>部门</label>
                        <select class="form-control" name="dp">
                            {% for item in depart_list %}
                            <option value="{{ item.id }}">{{ item.title }}</option>
                            {% endfor %}
                        </select>
                    </div>
                    <div class="form-group">
                        <button type="submit" class="btn btn-primary">提交</button>
                    </div>
                </form>
            </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
    • 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

3.Form

  1. views.py

    class MyForm(Form):
    	user = forms.CharField(wiget=forms.Input)
    	pwd = form.CharField(wiget=forms.Input)
    	age= form.CharField(wiget=forms.Input)
    	account = form.CharField(wiget=forms.Input)
    	create_time = form.CharField(wiget=forms.Input)
    	gender = form.CharField(wiget=forms.Input)
    	depart_id = form.CharField(wiget=forms.Input)
    
    def user_add(request):
    	form = MyForm() # 实例化
    	return render(request, 'user_add.html', {"form": form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  2. user_add.html

    form.user 相当于 input user

    <form method="post">
    	{{ form.user }}
    	{{ form.pwd }}
    <!--<input type="text" class="form-control" placeholder="姓名" name="user"/>-->
    
    </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    进一步优化,使用循环:

    <form method="post">
    	{ for field in form %}
    		{{ field }}
    	{% endfor %}
    </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5

4. ModelForm

  1. models.py

    class UserInfo(models.Model):
        """员工表"""
        name = models.CharField(verbose_name="姓名", max_length=16)
        password = models.CharField(verbose_name="密码", max_length=64)
        age = models.IntegerField(verbose_name="年龄")
        account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
        create_time = models.DateTimeField(verbose_name="入职时间")
        depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
        gender_choices = (
            (1, "男"),
            (2, "女"),
        )
        gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  2. views.py

    class MyForm(ModelForm):
    	class Meta:
    		model = UserInfo
    		fields = ["name", "password", "age"]
    def user_add(request):
    	form = MyForm() # 实例化
    	return render(request, 'user_add.html', {"form": form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  3. user_add.html

    form.user 相当于 input user

    <form method="post">
    	{{ form.user }}
    	{{ form.pwd }}
    <!--<input type="text" class="form-control" placeholder="姓名" name="user"/>-->
    
    </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    进一步优化,使用循环:

    <form method="post">
    	{ for field in form %}
    		{{ field }}
    	{% endfor %}
    </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5

5. 使用 ModelForm 添加用户

  1. views.py

    from django import forms
    
    class UserModelForm(forms.ModelForm):
        class Meta:
            model = models.UserInfo
            fields = ["name", "password", "age", "account", "create_time", "depart", "gender"]
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            # 循环找到所有插件,添加class="form-control"
            for name, field in self.fields.items():
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
    
    def user_model_form_add(request):
        """添加用户 ModelForm版本"""
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  2. models.py

    重写字段,保证 depart 作为用户列表的外键能够以字符形式显示。

    class Department(models.Model):
        """部门表"""
        title = models.CharField(verbose_name='标题', max_length=32)
        def __str__(self):
            return self.title
    
    • 1
    • 2
    • 3
    • 4
    • 5
  3. user_model_form_add.html

    {% extends 'layout.html' %}
    
    {% block content %}
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">用户列表</h3>
            </div>
            <div class="panel-body">
                <form method="post">
                    {% csrf_token %}
    
                    {% for field in form %}
                    <div class="form-group">
                        <label>{{ field.label }}</label>
                        {{ field }}
                    </div>
                    {% endfor %}
                    
                    <div class="form-group">
                        <button type="submit" class="btn btn-primary">提交</button>
                    </div>
                </form>
            </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
  4. 效果图

    在这里插入图片描述

6. 添加的错误提示

  1. views.py

    重写字段 name ,用于数据验证(name 字段至少为 3 个字符),
    name = forms.CharField(min_length=3, label="用户名")

    class UserModelForm(forms.ModelForm):
    
        # 重写字段
        name = forms.CharField(min_length=3, label="用户名")
    
        class Meta:
            model = models.UserInfo
            fields = ["name", "password", "age", "account", "create_time", "depart", "gender"]
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            # 循环找到所有插件,添加class="form-control"
            for name, field in self.fields.items():
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    def user_model_form_add(request):
        """添加用户 ModelForm版本"""
        if request.method == "GET":
            form = UserModelForm()
            return render(request, 'user_model_form_add.html', {"form": form})
    
        # 用户POST提交数据,数据校验
        form = UserModelForm(data=request.POST)
        if form.is_valid():
            # 如果数据合法,保存在数据库
            form.save()
            return redirect('/user/list/')
    
        # 校验失败(在页面上显示错误信息)
        else:
            return render(request, 'user_model_form_add.html', {"form": form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  2. user_model_form_add.html

    注意,网页自带的验证先取消 novalidate ,方便展示我们代码实现数据验证的效果。
    field.errors.0 显示当前的第一个错误。

    <form method="post" , novalidate>
        {% csrf_token %}
    
        {% for field in form %}
        <div class="form-group">
            <label>{{ field.label }}</label>
            {{ field }}
            <span style="color: red">{{ field.errors.0 }}</span>
        </div>
        {% endfor %}
        <div class="form-group">
            <button type="submit" class="btn btn-primary">提交</button>
        </div>
    </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  3. 效果图:

    在这里插入图片描述

2.13 用户管理:编辑

  • 点击编辑, 跳转到编辑界面(将编辑行的 ID 携带过去);
  • 编辑页面(默认数据,根据ID获取并设置到页面中)
  • 提交
    • 错误提示
    • 数据校验
    • 数据库更新
  1. user_list.html

    <a class="btn btn-primary btn-xs" href="/user/{{ obj.id }}/edit/">编辑</a>
    
    • 1
  2. urls.py
    编辑用户需要获取用户的id

    path('user/<int:nid>/edit/', views.user_edit),
    
    • 1
  3. views.py

    def user_edit(request, nid):
        """编辑用户"""
        # 根据id去数据库获取编辑行的数据
        row_object = models.UserInfo.objects.filter(id=nid).first()
    
        if request.method == "GET":
            # 加入instance参数,原有的值会显示在输入框
            form = UserModelForm(instance=row_object)
            return render(request, 'user_edit.html', {'form': form})
    
        form = UserModelForm(data=request.POST, instance=row_object)
        if form.is_valid():
            form.save()
            return redirect('/user/list/')
        return render(request, 'user_edit.html', {"form":form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  4. 效果图

    在这里插入图片描述

2.14 用户管理:删除

  1. user_list.html

    修改删除标签

    <a class="btn btn-danger btn-xs" href="/user/{{ obj.id }}/delete/">删除</a>
    
    • 1
  2. urls.py

    path('user/<int:nid>/delete/', views.user_delete)
    
    • 1
  3. views.py

    def user_delete(request, nid):
        models.UserInfo.objects.filter(id=nid).delete()
        return redirect('/user/list/')
    
    • 1
    • 2
    • 3

3 案例:靓号管理

3.1 表结构

在这里插入图片描述

class PrettyNum(models.Model):
    """靓号表"""
    mobile = models.CharField(verbose_name="手机号", max_length=11)
    # 想要允许为空 null=True, blank=True
    price = models.IntegerField(verbose_name="价格", default=0)
    level_choices = (
        (1, "1级"),
        (2, "2级"),
        (3, "3级"),
        (4, "4级"),
    )
    level = models.SmallIntegerField(verbose_name="级别", choices=level_choices, default=1)
    status_choices = (
        (1, "已占用"),
        (2, "未使用"),
    )
    status = models.SmallIntegerField(verbose_name="状态", choices=status_choices, default=2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.2 靓号列表

  • URL;
  • 函数
    • 获取所有靓号;
    • 结合 html + render 将所有靓号展现出来;
  1. layout.html

    <li><a href="/pretty/list/">靓号管理</a></li>
    
    • 1
  2. urls.py

    path('pretty/list/', views.pretty_list),
    
    • 1
  3. views.py

    def pretty_list(request):
        """靓号管理"""
    
        # order_by :降序
        queryset = models.PrettyNum.objects.all().order_by("-level")
        return render(request, 'pretty_list.html', {'queryset': queryset})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  4. pretty.html

    {% extends 'layout.html' %}
    {% block content %}
    
    <div class="container">
        <div style="margin-bottom: 10px">
            <a class="btn btn-success" href="#">新建靓号</a>
        </div>
        <div class="panel panel-default">
            <div class="panel-heading">
                <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
                用户列表
            </div>
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>手机号</th>
                    <th>价格</th>
                    <th>级别</th>
                    <th>状态</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {% for obj in queryset %}
                <tr>
                    <td>{{ obj.id }}</td>
                    <td>{{ obj.mobile }}</td>
                    <td>{{ obj.price }}</td>
                    <td>{{ obj.get_level_display }}</td>
                    <td>{{ obj.get_status_display }}</td>
                    <td>
                        <a class="btn btn-primary btn-xs" href="#">编辑</a>
                        <a class="btn btn-danger btn-xs" href="#">删除</a>
                    </td>
                </tr>
                {% endfor %}
                </tbody>
            </table>
        </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

3.3 新建靓号

  • 列表点击跳转:/pretty/add/
  • URL
  • ModelForm 类
  • 函数
    • 实例化类对象;
    • 通过 render 将对象传入到 HTML 中;
    • 模板循环展示所有对象;
  • 点击提交
    • 数据校验; 【两种方法】
    • 保存到数据库;
    • 跳转回靓号列表;
  1. urls.py

    path('pretty/add/', views.pretty_add),
    
    • 1
  2. views.py

    from django.core.validators import RegexValidator
    from django.core.validators import ValidationError
    class PrettyModelForm(forms.ModelForm):
        # 验证:方式1 字段+正则
        # mobile = forms.CharField(
        #     label="手机号",
        #     validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式错误')],
        # )
        class Meta:
            model = models.PrettyNum
            # fields = ["mobile", "price", "level", "status"]
            fields = "__all__"
            # exclude = ['level']
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            for name, field in self.fields.items():
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
        # 验证:方式2 钩子方法 
        def clean_mobile(self):
            txt_mobile = self.cleaned_data['mobile']
            if len(txt_mobile) != 11:
                # 验证不通过
                raise ValidationError("格式错误")
            # 验证通过
            return txt_mobile
    
    • 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
    def pretty_add(request):
        """添加靓号"""
        if request.method == "GET":
            form = PrettyModelForm()
            return render(request, 'pretty_add.html', {'form': form})
    
        # POST提交数据,数据校验
        form = PrettyModelForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('/pretty/list/')
    
        # 校验失败
        else:
            return render(request, 'pretty_add.html', {'form': form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  3. pretty_list.html

    <a class="btn btn-success" href="/pretty/add/">新建靓号</a>
    
    • 1
  4. pretty_add.html

{% extends 'layout.html' %}
{% block content %}
<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">靓号列表</h3>
        </div>
        <div class="panel-body">
            <form method="post" novalidate>
                {% csrf_token %}

                {% for field in form %}
                <div class="form-group">
                    <label>{{ field.label }}</label>
                    {{ field }}
                    <span style="color: red">{{ field.errors.0 }}</span>
                </div>
                {% endfor %}
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">提交</button>
                </div>
            </form>
        </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
  1. 效果图
    在这里插入图片描述

  2. 数据校验的补充:数据库的手机号需要唯一

    使用正则表达式判断 「手机号是否已经存在」

    # True/False
    exists = models.PrettyNum.objects.ilter(mobile="100000000").exists()
    
    • 1
    • 2

    效果图:

    在这里插入图片描述
    views.py

    class PrettyModelForm(forms.ModelForm):
        class Meta:
            model = models.PrettyNum
            fields = "__all__"
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            for name, field in self.fields.items():
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
        # 验证:方式2
        def clean_mobile(self):
            txt_mobile = self.cleaned_data['mobile']
    			
    		# 手机号是否唯一的判断 
            exists = models.PrettyNum.objects.filter(mobile=txt_mobile).exists()
            if exists:
                raise ValidationError("手机号已存在")
                
            return txt_mobile
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

3.4 编辑靓号

  1. urls.py

    path('pretty/<int:nid>/edit/', views.pretty_edit),
    
    • 1
  2. views.py

    class PrettyEditModeleForm(forms.ModelForm):
        # disabled参数,该字段不可以编辑
        # mobile = forms.CharField(disabled=True, label="手机号")
        class Meta:
            model = models.PrettyNum
            #fields = ["price", "level", "status"]
            fields = "__all__"
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            for name, field in self.fields.items():
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
        # 验证:方式2
        def clean_mobile(self):
    
            # 当前编辑行的id
            # self.instance.pk
    
            txt_mobile = self.cleaned_data['mobile']
    
    		# 手机号是否唯一的判断
            exists = models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()
            if exists:
                raise ValidationError("手机号已存在")
            
            if len(txt_mobile) != 11:
                # 验证不通过
                raise ValidationError("格式错误")
            # 验证通过
            return txt_mobile
    
    
    • 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
    def pretty_edit(request, nid):
        """编辑靓号"""
    
        # 根据id去数据库获取编辑行的数据
        row_object = models.PrettyNum.objects.filter(id=nid).first()
    
        if request.method == "GET":
            form = PrettyEditModeleForm(instance=row_object)
            return render(request, 'pretty_edit.html', {'form': form})
    
        form = PrettyEditModeleForm(data=request.POST, instance=row_object)
        if form.is_valid():
            form.save()
            return redirect('/pretty/list/')
    
        return render(request, 'pretty_edit.html', {'form': form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  3. pretty_list.html

    <a class="btn btn-primary btn-xs" href="/pretty/{{ obj.id }}/edit/">编辑</a>
    
    • 1
  4. pretty_edit.html

    {% extends 'layout.html' %}
    {% block content %}
    
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">编辑靓号</h3>
            </div>
            <div class="panel-body">
                <form method="post" novalidate>
                    {% csrf_token %}
    
                    {% for field in form %}
                    <div class="form-group">
                        <label>{{ field.label }}</label>
                        {{ field }}
                        <span style="color: red">{{ field.errors.0 }}</span>
                    </div>
                    {% endfor %}
                    <div class="form-group">
                        <button type="submit" class="btn btn-primary">提交</button>
                    </div>
                </form>
            </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
  5. 效果图

    在这里插入图片描述

  6. 数据校验:确保手机号的唯一性。

    这和新建靓号中的校验不太一样。新建靓号的时候,对于新输入的手机号,是和数据库中的手机号相比判断的。

    编辑靓号中,如果你更改的是手机号除外的信息,此时也没办法通过,因为你编辑后提交的手机号在数据库中已经存在了,因此在进行校验的时候需要排除自身的手机号再判断唯一性。

    views.py

    txt_mobile = self.cleaned_data['mobile']
    
    # 当前编辑行的id
    # self.instance.pk
    exists = models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()
    
    if exists:
    	raise ValidationError("手机号已存在")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    效果图,编辑当前手机号的级别:

    在这里插入图片描述

3.5 删除靓号

  1. pretty_list.html

    修改删除标签

    <a class="btn btn-danger btn-xs" href="/pretty/{{ obj.id }}/delete/">删除</a>
    
    • 1
  2. urls.py

    path('pretty/<int:nid>/delete/', views.pretty_delete),
    
    • 1
  3. views.py

    def pretty_delete(request, nid):
    	models.PrettyNum.objects.filter(id=nid).delete()
    	return redirect('/pretty/list/')
    
    • 1
    • 2
    • 3

3.6 靓号管理:手机号搜索

  1. 数据库搜索相关知识补充

    models.PrettyNum.objects.filter(mobile="12345678920", id=5)
        
    # 以字典方式传入 必须要加 ** 
    data_list = {"mobile": "12345678920", "id": 5}
    models.PrettyNum.objects.filter(**data_list)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    models.PrettyNum.objects.filter(id=5)       # 等于5
    models.PrettyNum.objects.filter(id__gt=5)    # 大于5
    models.PrettyNum.objects.filter(id__gte=5)   # 大于等于5
    models.PrettyNum.objects.filter(id__lt=5)    # 小于5
    models.PrettyNum.objects.filter(id__lte=5)   # 小于等于5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    models.PrettyNum.objects.filter(mobile="123")               # 等于
    models.PrettyNum.objects.filter(mobile__startswith="123")    # 以123开头
    models.PrettyNum.objects.filter(mobile__endswith="123")      # 以123结尾
    models.PrettyNum.objects.filter(mobile__contains="123")      # 包含123
    
    • 1
    • 2
    • 3
    • 4
  2. 手机号搜索实现

    本质:

    在用户列表界面增加一个输入框,用来输入查询的手机号。

    我们希望进行搜索时,条件会包含在网址里,即网址是 http://127.0.0.1:8000/pretty/list/?q=456 ,那么需要通过 get 方式提交,即 <form method="get"> 。那么后端会通过 request.GET.get 获取到 name="q" 的输入,将其放入字典 data_list ,作为数据库搜索的条件 filter(**data_list)

    要想让输入框能够显示查询的手机号,需要把输入值 search_data 传入前端,放在<input> 标签的 value 字段。

views.py

def pretty_list(request):
    """靓号管理"""
    data_list = {}
    search_data = request.GET.get('q', "")
    if search_data:
         data_list["mobile__contains"] = search_data

    queryset = models.PrettyNum.objects.filter(**data_list).order_by("-level")
    return render(request, 'pretty_list.html', {'queryset': queryset, "search_data": search_data})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

pretty_list.html

    <div style="margin-bottom: 10px" class="clearfix">
        <a class="btn btn-success" href="/pretty/add/">新建靓号</a>
        <div style="float: right; width:300px">
            <form method="get">
                <div class="input-group">
                    <input type="text" name="q" class="form-control" placeholder="Search for..."
                           value="{{ search_data }}">
                    <span class="input-group-btn">
                    <button class="btn btn-default" type="submit">
                        <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
                    </button>
                </span>
                </div><!-- /input-group -->
            </form>
        </div>
    </div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

效果图:

在这里插入图片描述

3.7 靓号管理:分页

pass (笔记未整理)

  1. pagination.py

    """
    自定义分页组件
    如果以后想要使用这个分页组件,需要做如下几件事:
    
    在视图函数中:
        def pretty_list(request):
    
            # 1. 根据自己的情况去筛选数据
            queryset = models.PrettyNum.objects.filter(**data_list).order_by("-level")
    
            # 2. 实例化分页对象
            page_objects = Pagination(request, queryset) # 封装成组件
    
            context = {
                'search_data': search_data,
                'queryset': page_objects.page_queryset,  # 分完页的数据
                "page_string": page_objects.html() # 生成的页码
            }
            return render(request, 'pretty_list.html', context)
    
    # 在HTML中:
        {% for obj in queryset %}
            {{ obj.xx }}
        {% endfor %}
    
        <ul class="pagination">
            {{ page_string }}
        </ul>
    """
    from django.utils.safestring import  mark_safe
    
    
    class Pagination(object):
    
        def __init__(self, request, queryset, page_size=10, page_param="page", plus=5):
            """
            :param request:     请求的对象
            :param queryset:    符合条件的数据 (根据这个数据给他进行分页处理)
            :param page_size:   每页显示多少条数据
            :param page_param:  在URL中传递的获取分页的参数 例如:pretty/list/?page=1
            :param plus:        显示当前页的前后几页(页码)
            """
            import copy
            query_dict = copy.deepcopy(request.GET)
            query_dict.mutable = True
            self.query_dict = query_dict
    
            self.page_param = page_param
            page = int(request.GET.get(page_param, "1"))
            self.page = page
            self.page_size = page_size
            self.start = (page - 1) * page_size
            self.end = page * page_size
            self.page_queryset = queryset[self.start:self.end]
    
            total_count = queryset.count()
            # 总页码数
            total_page_count, div = divmod(total_count, page_size)
            if div:
                total_page_count += 1
            self.total_page_count = total_page_count
            self.plus = plus
    
    
        def html(self):
            # 计算当前页的前5页与后5页
            if self.total_page_count <= 2 * self.plus + 1:
                start_page = 1
                end_page = self.total_page_count + 1
            else:
                if self.page <= self.plus:
                    start_page = 1
                    end_page = 2 * self.plus + 1
                else:
                    if (self.page + self.plus) > self.total_page_count:
                        start_page = self.total_page_count - 2 * self.plus
                        end_page = self.total_page_count
                    else:
                        start_page = self.page - self.plus
                        end_page = self.page + self.plus
    
            page_str_list = []
    
            # 首页
            self.query_dict.setlist(self.page_param, [1])
            page_str_list.append('<li><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode()))
    
            # 上一页
            if self.page > 1:
                self.query_dict.setlist(self.page_param, [self.page - 1])
                prev = '<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode())
            else:
                self.query_dict.setlist(self.page_param, [1])
                prev = '<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode())
            page_str_list.append(prev)
    
            # 生成页码
            for i in range(start_page, end_page):
                self.query_dict.setlist(self.page_param, [i])
                if i == self.page:
                    ele = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
                else:
                    ele = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
                page_str_list.append(ele)
    
            # 下一页
            if self.page < self.total_page_count:
                self.query_dict.setlist(self.page_param, [self.page + 1])
                prev = '<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode())
            else:
                self.query_dict.setlist(self.page_param, [self.total_page_count])
                prev = '<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode())
    
            page_str_list.append(prev)
    
            # 尾页
            self.query_dict.setlist(self.page_param, [self.total_page_count])
            page_str_list.append('<li><a href="?{}">尾页</a></li>'.format(self.query_dict.urlencode()))
    
            page_string = mark_safe("".join(page_str_list))
            return page_string
    
    • 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
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
  2. views.py

    from app01.utils.pagination import Pagination
    
    def pretty_list(request):
        """靓号管理"""
        data_list = {}
        search_data = request.GET.get('q', "")
        if search_data:
             data_list["mobile__contains"] = search_data
    
        queryset = models.PrettyNum.objects.filter(**data_list).order_by("-level")
    
        page_objects = Pagination(request, queryset) # 封装成组件
    
        context = {
            'search_data': search_data,
            'queryset': page_objects.page_queryset,  # 分完页的数据
            "page_string": page_objects.html() # 生成的页码
        }
        return render(request, 'pretty_list.html', context)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  3. pretty_list.html

        <div class="clearfix">
            <ul class="pagination">
                {{page_string}}
                <li>
                    <form method="get">
                        <div class="input-group" style="width: 200px">
                            <input type="text" name="page" class="form-control" placeholder="页码">
                            <span class="input-group-btn">
                    <button class="btn btn-default" type="submit">跳转</button>
                </span>
                        </div>
                    </form>
                </li>
            </ul>
        </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

视频3-10还有一半未看。

4 时间选择组件

  1. 效果展示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/38585175e498498b90b21bbcc6371528.png)
  • 1
  1. 引入 bootstrap-datepicker

    {% block css %}
    	<link rel="stylesheet" href="{% static '/plugins/bootstrap-datepicker-master/dist/css/bootstrap-datepicker.min.css' %}">
    {% endblock %}
    
    • 1
    • 2
    • 3
    {% block js %}
        <script src="{% static '/plugins/bootstrap-datepicker-master/dist/js/bootstrap-datepicker.min.js' %}"></script>
        <script src="{% static '/plugins/bootstrap-datepicker-master/dist/locales/bootstrap-datepicker.zh-CN.min.js' %}"></script>
    {% endblock %}
    
    • 1
    • 2
    • 3
    • 4
  2. user_add.html 时间函数 ,其中 #dt 对应入职时间的ID

    <input type="text" id="dt" class="form-control" placeholder="入职时间" name="ctime"/>
    
    • 1
        <script>
            $(function() {
                $('#dt').datepicker({
                    format: 'yyyy-mm-dd',
                    startDate: '0',
                    language: "zh-CN",
                    autoclose: true
                })
            })
        </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  3. user_model_form_add.html 时间函数 ,modelform中的ID默认为 ID_字段名,即 #id_create_time

        <script>
            $(function() {
                $('#id_create_time').datepicker({
                    format: 'yyyy-mm-dd',
                    startDate: '0',
                    language: "zh-CN",
                    autoclose: true
                })
            })
        </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

5 BootStrap 样式父类

  1. 重复的内容可以集成为父类, 比如样式设置:

    在这里插入图片描述

    from django import forms
    
    class BootStrapModelForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            # 循环找到所有插件,添加class="form-control"
            for name, field in self.fields.items():
                # 字段中有属性,保留原有属性,没有属性,才增加
                if field.widget.attrs:
                    field.widget.attrs["class"] = "form-control"
                    field.widget.attrs["placeholder"] = field.label
                else:
                    field.widget.attrs = {
                        "class": "form-control",
                        "placeholder": field.label
                    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  2. 之后,所有涉及到样式设置的 ModelForm 可以直接继承 BootStrap ,比如:

    class UserModelForm(BootStrapModelForm):
    
    • 1

6 views 函数拆分

由于已经实现了许多功能,原本的 views 函数显得复杂,此时可以新建一个 views 目录,将各个功能拆分成若干个 .py 文件。

注意,原本的 views.py 需要删除。

在这里插入图片描述

urls.py 也需要修改。

在这里插入图片描述

注意, models.py 函数不能像这样拆分。

7 案例:管理员

7.1


参考资料:

  1. Windows安装mysql详细步骤(通俗易懂,简单上手)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/73804
推荐阅读
相关标签
  

闽ICP备14008679号

        
cppcmd=keepalive&