关键词搜索

源码搜索 ×
×

Django之MTV实战(2)

发布2021-09-23浏览320次

详情内容

辅助视频教程:

Python基础教程|xin3721自学网ul li id=itemtitlePython3 从入门到精通视频教程/li /ul ul li class=description Python是一种跨平台的计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),icon-default.png?t=L892https://www.xin3721.com/eschool/pythonxin3721/

1. 回顾知识

上一篇文章已经教会了大家怎么安装Django和简单的配置,相信大家应该早就学会了,那么我们在回忆一下吧,懂的同学可跳过这章节。

1.1 新增工程

django-admin startproject <自定义工程名称>

(py369) [python@localhost Python]$ django-admin startproject devops 
复制

1.2 创建新的APP

python manage.py startapp <自定义APP名称>

(py369) [python@localhost devops]$ python manage.py startapp hello
复制

1.3 注册APP

devops->settings.y里面t添加:

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. # 第一种方式
  9. 'hello.apps.HelloConfig',
  10. # 第二种方式,直接写hello也行
  11. 'hello',
  12. ]
复制

1.4 编写URL和VIEW

在devops下的主路由urls.py

  1. from django.contrib import admin
  2. from django.urls import path,include
  3. from views import index
  4. urlpatterns = [
  5. path('admin/', admin.site.urls),
  6. path('', index.index),
  7. # 引导到hello下的路由URL(也叫子路由)
  8. path('hello/', include('hello.urls'))
  9. ]
复制

在hello下的子路由urls.py

  1. from django.urls import path
  2. from hello import view
  3. app_name = 'hello'
  4. urlpatterns = [
  5. # 普通url参数
  6. path('', view.index, name='index'),
复制

hello下的view.py代码:

  1. from django.http import HttpResponse
  2. def index(request):
  3. return HttpResponse('hello django')
复制

1.5 验证结果如下:

2. 基本概念

2.1 专业术语

MTV简写:

  • M:model,这个是对应数据库的,简单理解就是对应数据库的表。

  • T:template,这个对应的是HTML模板,前端渲染用的。

  • V:view,这个对应的是后台python执行脚本了。

通俗的一句话:用户发送http请求,匹配url后执行view脚本返回模板template,用户看到了网页的展示效果(渲染)

2.2 MTV之视图

2.2.1 request对象

2.2.2 Respone对象

下面详细介绍下...

2.2.3 GET请求

  • GET请求,不带参数

    网页输入这样的格式,是不带参数

    https://192.168.8.130:8888/hello
    复制

    备注:如上面演示的就是不带参数。

  • GET请求,?+参数

    比较常用的方式?+参数

    在浏览器输入如下地址:

    http://192.168.8.130:8888/hello/?year=2020&month=09&day=02
    复制

    说明: 参数:year month day

    网址匹配到路由hello/url.py 的配置规则

    1. from django.urls import path
    2. from hello import view
    3. app_name = 'hello'
    4. urlpatterns = [
    5. # 普通参数
    6. path('', view.index, name='index'),
    7. ]
    复制

    后台视图hello/view.py代码配置如下:

    1. from django.http import HttpResponse
    2. def index(request):
    3. print(request.GET)
    4. return HttpResponse("year is {}, month is {}, day is {}.".format(year, month, day))
    复制

    后台打印输出的结果如下:
    备注: 是一个QueryDict对象。

    <QueryDict: {'year': ['2020'], 'month': ['09'], 'day': ['02']}>
    复制

    从上面已经接收到用户的信息了,就可以获取相应的参数了,hello/view后台脚本更新如下:

    1. from django.http import HttpResponse
    2. def index(request):
    3. #第一个参数是获取QueryDict的year
    4. #第二参数是默认值,表示拿不到数据,用缺省值
    5. year = request.GET.get('year', '2030')
    6. month = request.GET.get('month', 'Sep')
    7. day = request.GET.get('day', '8')
    8. return HttpResponse("year is {}, month is {}, day is {}.".format(year, month, day))
    复制

    网页请求带参数返回的结果如下:

    网页请求不带参数返回的结果如下:

  • GET请求,位置参数

    不推荐使用,位置要一一对应入座

    网址匹配到路由hello/url.py配置规则

    1. from django.urls import re_path
    2. from hello import view
    3. app_name = 'hello'
    4. urlpatterns = [
    5. # 位置参数
    6. # [0-9]表示数字0-9,{4}表示取4位数字
    7. re_path('([0-9]{4})/([0-9]{2})/([0-9]{2})/', view.index, name='index'),
    8. ]
    复制

    后台视图hello/view.py脚本配置如下:

    1. def index(request, year, month, day):
    2. return HttpResponse("year is {}, month is {}, day is {}.".format(year, month, day))
    复制

    网页输入如下地址,请求返回的结果如下:

  • GET请求,关键字参数

    说明:强烈推荐,优雅的方式.

    在浏览器输入如下地址:

    http://192.168.8.130:8888/2020/09/02
    复制

    路由视图hello/url.py配置规则

    1. from django.urls import re_path
    2. from hello import view
    3. app_name = 'hello'
    4. urlpatterns = [
    5. # 关键字参数,(?<参数名>参数类型)
    6. re_path('(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})', view.index, name='index'),
    7. ]
    复制

    后台视图hello/view.py脚本配置如下:

    1. from django.http import HttpResponse
    2. def index(request, **kwargs):
    3. # 输出结果:{'year': '2020', 'month': '09', 'day': '02'}
    4. print(kwargs)
    5. year = kwargs.get('year')
    6. month = kwargs.get('month')
    7. day = kwargs.get('day')
    8. return HttpResponse("year is {}, month is {}, day is {}.".format(year, month, day))
    复制

    还可以换成另外一种写法,更加灵活,但是用的也不是很多:

    1. from django.http import HttpResponse
    2. # 不用考虑到函数参数的位置
    3. def index(request, day, month, year):
    4. return HttpResponse("year is {}, month is {}, day is {}.".format(year, month, day))
    复制

2.2.4 POST请求

在devops/setting.py里把csrf关闭,不然会运行报错:

  1. MIDDLEWARE = [
  2. 'django.middleware.security.SecurityMiddleware',
  3. 'django.contrib.sessions.middleware.SessionMiddleware',
  4. 'django.middleware.common.CommonMiddleware',
  5. # 默认开启防止中间人CSRF攻击,前期先注释掉
  6. # 'django.middleware.csrf.CsrfViewMiddleware',
  7. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  8. 'django.contrib.messages.middleware.MessageMiddleware',
  9. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  10. ]
复制

网址匹配到路由hello/urls.py配置规则

  1. from django.urls import path
  2. from hello import view
  3. app_name = 'hello'
  4. urlpatterns = [
  5. path('', view.index, name='index'),
  6. ]
复制

后台视图hello/view.py脚本配置如下:

  1. from django.http import HttpResponse, QueryDict
  2. def index(request):
  3. if request.method == "POST":
  4. # POST方法
  5. print(request.method)
  6. # body是字节编码,b'year=2020&month=09&day=13'
  7. print(request.body)
  8. # 转换为字典{'year': '2020', 'month': '09', 'day': '13'}
  9. print(QueryDict(request.body).dict())
  10. # <QueryDict: {'year': ['2020'], 'month': ['09'], 'day': ['13']}>
  11. print(request.POST)
  12. data = request.POST
  13. year = data.get('year', '2030')
  14. month = data.get('month', '9')
  15. day = data.get('day', '8')
  16. return HttpResponse("year is {}, month is {}, day is {}.".format(year, month, day))
复制

模拟触发POST流量:

  1. [root@localhost ~]# curl -X POST http://192.168.8.130:8888/hello/ -d 'year=2020&month=09&day=13'
  2. year is 2030, month is 9, day is 13.
复制

看看我们后台接收哪些信息:

2.2.5 QueryDict介绍

在httprequest对象中,GET和POST属性是django.http.QueryDict的实例,它是一个自定义的类似字典的类,用来处理同一个键带多个值。无论使用GET,POST方式,他们最终都是通过QueryDict方法对传入的参数进行处理。

3. MTV之模板

3.1 模板继承

3.1.1 常规手段

  • 创建模板templates目录及子目录hello

    mkdir -p devops/templates/hello
    复制

    备注:每一个APP对应一个目录。

  • 路由视图hello/urls.py配置规则

    1. from django.urls import path
    2. from hello import view
    3. app_name = 'hello'
    4. urlpatterns = [
    5. path('list/', view.list, name='list'),
    6. ]
    复制
  • 后台视图hello/view.py配置

    1. from django.shortcuts import render
    2. def list(request):
    3. users = [
    4. {'username':'test01', 'age':18, 'hobby':'python'},
    5. {'username':'test02', 'age':18, 'hobby':'java'},
    6. {'username':'test01', 'age':18, 'hobby':'C'},
    7. ]
    8. return render(request, 'hello/list.html', {'users':users})
    复制

    说明:本次练习,还没涉及到数据库,所以先本地创建数据。

  • 新建模板

    templates/hello/list.html配置

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>点滴技术</title>
    6. </head>
    7. <body>
    8. <p style="background-color: #77ee77">用户列表</p>
    9. <table border="1">
    10. <thead style="background-color: #00aced">
    11. <tr>
    12. <td>username</td>
    13. <td>age</td>
    14. <td>hobby</td>
    15. </tr>
    16. </thead>
    17. <tbody>
    18. {% for user in users %}
    19. <tr>
    20. <td> {{ user.username }} </td>
    21. <td> {{ user.age }} </td>
    22. <td> {{ user.hobby }} </td>
    23. </tr>
    24. {% endfor %}
    25. </tbody>
    26. </table>
    27. <p style="background-color: yellow"> 版权所有©点滴技术 </p>
    28. </body>
    29. </html>
    复制
  • 网页输入地址后,效果图:

3.1.2 模板继承

  • 定义母板
    devops/templates目录下新增一个base.html母板。

    1. <!doctype html>
    2. <html lang="en">
    3. <head>
    4. <!-- 每个html的标签变量,都可以自定义-->
    5. <title>
    6. {% block title %}NetDevOps{% endblock title %}
    7. </title>
    8. </head>
    9. <body>
    10. <!-- body变量,每个页面都可以自定义内容-->
    11. {% block body %}这是body的内容{% endblock body %}
    12. <!-- 底部,每个html页面固定样式 -->
    13. <p style="background-color: yellow"> 版权所有©点滴技术 </p>
    14. </body>
    15. </html>
    复制
  • 子页面继承

    1. <!--继承母版-->
    2. {% extends "base.html" %}
    3. <!--重写title的内容-->
    4. {% block title %} 用户的列表 {% endblock %}
    5. <!--重写body的内容-->
    6. {% block body %}
    7. <table border="1">
    8. <thead style="background-color: #00aced" >
    9. <tr>
    10. <td>username</td>
    11. <td>age</td>
    12. <td>hobby</td>
    13. </tr>
    14. </thead>
    15. <tbody>
    16. {% for user in users %}
    17. <tr>
    18. <td> {{ user.username }} </td>
    19. <td> {{ user.age }} </td>
    20. <td> {{ user.hobby }} </td>
    21. </tr>
    22. {% endfor %}
    23. </tbody>
    24. </table>
    25. {% endblock%}
    复制

    备注:公共部分代码就不用写出来了,减少了代码冗余。

  • 视图hello/view.py配置

    1. from django.shortcuts import render
    2. def userlist(request):
    3. users = [
    4. {'username':'test01', 'age':18, 'hobby':'python'},
    5. {'username':'test02', 'age':18, 'hobby':'java'},
    6. {'username':'test03', 'age':18, 'hobby':'C'},
    7. ]
    8. return render(request, 'hello/userlist.html', {'users':users})
    复制
  • 效果图:

4. Template模板过滤器

4.1 Django自带常用过滤器

  • 传入参数的长度

    1. {% if messages|length >= 3 %}
    2. The Messages is too long.
    3. {% else %}
    4. The messages is too short.
    5. {% endif %}
    复制
  • default:缺省值

    1. {{ messages|default:"nothing" }}
    复制

    备注:如果传入的值为false,则使用缺省值。

  • first/last

    1. {{ messages|first }}
    2. {{ messages|last }}
    复制

    备注:显示列表第一个或最后一个元素。

  • join
    说明:将列表转为字符串。

    1. {{ value|join:"-" }}
    复制
  • length
    说明:判断长度,返回布尔值

    1. {{ messages|length}}
    2. {{ messages|length_is:"4"}}
    复制
  • static
    说明:加载本地图片、css、js样式等资源,通常使用CDN方式。

    1. # 方法1
    2. {% load static %}
    3. <img src="{% static "images/favicon.png" %}" alt="Hi!" />
    4. # 方法2
    5. {% load static %}
    6. {% static "images/favicon.png" as myphoto %}
    7. <img src="{{ myphoto }}"></img>
    复制
  • date
    说明:时间格式化,返回年-月-日 时-分-秒

    1. {{ messages|date:"Y/m/d" }}{{ messages|date:"H:i:s" }}
    复制
  • safe
    说明:缺省情况下,django会对HTML等标签进行自动转义,如果要关闭自动转义,可通过过滤器"|safe"的方式申明不用转义。

    1. value = "<a href="https://www.python.org"> 百度链接 </a>"
    2. {{ value|safe }}
    复制
  • csrf_token
    说明:用于跨站请求伪造保护

    1. <form action="" method='post'>
    2. {% csrf_token %} # 有了这个POST请求才能正常运行
    3. <p> <input type="text" name="user"></p>
    4. <input type="submit">
    5. </form>
    复制
  • slice
    说明:切片

    1. {{ messages|slice:":2"}}
    复制

4.2 自定义模板标签和过滤器

  • 定义标签
    创建目录及文件:hello/templatetags/mytag.py

    1. from django import template
    2. register = template.Library()
    3. @register.filter
    4. def test(x, y):
    5. return int(x)*2 + int(y)qq
    复制
  • 模板视图

    1. <!--继承母版-->
    2. {% extends "base.html" %}
    3. {% block title %}模板标签{% endblock %}
    4. <!--重写body的内容-->
    5. {% block body %}
    6. <!--自定义模板标签-->
    7. {% load mytag %}
    8. <p> {{ "https://cdn.jxasp.com:9143/image/2"|test:"1" }}</p>
    9. {% endblock%}
    复制

5. 模型Model基础

5.1 模型概念

简单理解:模型对应数据库中的表,模型中的一个类对应数据库一张表;

5.1.1 常用字段类型

  • 字符串:CharFieLd

    1. from django.db import models
    2. class User():
    3. username = models.CharField(max_length=20)
    复制
  • 整数:IntegerField

    int_field = models.IntegerField()
    复制
  • 浮点数:FloatField

    float_field = models.FloatField()
    复制
  • 自增字段:AutoField

    id_field = models.AutoField(primary_key=True)
    复制
  • 文本框:TextField

    text_field = models.TextField()
    复制
  • 邮箱:EmailField
    说明:用于检查邮箱的合法性。

    mail_field = models.EmailField()
    复制
  • 日期:DateField

    说明:auto_now是被保存时,将时间设置为当前时间,通常表示last-modifiedauto_now_add是首次被创建时,设置为当前时间,通常表示创建时间。

    date = models.DateField()
    复制
  • 文件上传:Filefield
    说明:upload_to必选参数,指文件的上传存放路径。

    upload_file = models.FileField(upload_to='/usr/tmp/test')
    复制

5.1.2 常用字段参数

  • null
    如果null=True将再数据库存放一个空值NULL,缺省为Flase。
    该字段是可以在数据中存放null值。
  • blank
    如果blank=True,则允许该字段为空白,缺省是False,不允许为空。
    该字段是表单验证是否允许为空或不为空的。
  • unique
    如果unique=True,表示该字段在整个表单中是唯一的,不重复的。
  • primary_key
    如果primary_key=True, 表示该字段在数据库中是主键。
  • default = ''
    用于定义缺省值。
  • verbose_name
    ForeignKeyManyToManyField、和OneToOneField的备注信息需要用到这个。

6. 建模及同步

6.1 设计一个简单的模型

hello\models.py

  1. #!/usr/bin/env python3
  2. #-*- coding:UTF-8 -*-
  3. from django.db import models
  4. class Devices(models.Model):
  5. device_name = models.CharField(max_length=32, help_text='设备名称')
  6. ip = models.CharField(max_length=15, help_text='管理IP地址')
  7. vendor = models.CharField(max_length=16, help_text='厂商')
  8. device_type = models.CharField(max_length=6, help_text='设备类型')
  9. model = models.CharField(max_length=32, help_text='设备型号')
  10. sn = models.CharField(max_length=32, help_text='序列号')
  11. os = models.CharField(max_length=16, help_text='操作系统')
  12. version = models.CharField(max_length=32, help_text='版本')
  13. def __str__(self):
  14. return self.device_name
复制

6.2 将模型同步到数据库

  • 生成迁移脚本

    1. (py369) [root@localhost devops]# python manage.py makemigrations hello
    2. Migrations for 'hello':
    3. hello/migrations/0004_devices.py
    4. - Create model Devices
    复制
  • 展示迁移的sql语句

    1. (py369) [root@localhost devops]# python manage.py sqlmigrate hello 0004
    2. BEGIN;
    3. --
    4. -- Create model Devices
    5. --
    6. 此处省略...
    复制
  • 执行数据库命令

    1. (py369) [root@localhost devops]# python manage.py migrate hello
    2. Operations to perform:
    3. Apply all migrations: hello
    4. Running migrations:
    5. Applying hello.0004_devices... OK
    复制
  • 查看数据库表

  • 常用命令解释

    1. # 生产迁移脚本
    2. python manage.py makemigrations <app_name>
    3. # 转换后的sql语句
    4. python manage.py sqlmigrate <app_name> <number>
    5. # 执行数据库命令
    6. python manage.py migrate
    7. # 所有APP及对应生效的migration
    8. python manage.py showmigrations
    9. # 将某个APPmigration重置
    10. python manage.py migrate --fake hello
    11. # 强制执行某个版本的迁移脚本
    12. python manage.py migrate --fake hello
    13. python manage.py migrate --fake hello 0004
    复制

7. ORM实现简单的增删改查

7.1 ORM概念

  • ORM是对数据抽象建模并提供访问接口的编程方式
  • 模型中的一个类(class)表示一个表(table)
  • 每一个属性对应数据表中的一个字段
  • 调用数据表,就是实例化类的对象

7.2 增 | 删 | 改 | 查

7.2.1 增加数据

  1. (py369) [root@localhost devops]# python manage.py shell
  2. In [1]: from hello.models import Devices
  3. # 实例化对象
  4. In [4]: D = Devices.objects.all()
  5. In [5]: D
  6. # 暂时还没有数据,为空
  7. Out[5]: <QuerySet []>
  8. In [7]: data = {'device_name':'test-sw-01', 'ip':'192.168.1.1', 'vendor':'cisco','device_type':'switch','model':'c3850','sn':'001','os':'ios','version':'15.0'}
  9. # 第一种创建方式(最常用)
  10. In [8]: D.create(**data)
  11. Out[8]: <Devices: test-sw-01>
  12. # 第二种创建方式(防止重复,速度相对较慢):
  13. # 返回一个元组(对象,TrueFalse
  14. In [10]: data2 = {'device_name':'test-sw-02', 'ip':'192.168.1.2', 'vendor':'cisco','device_type':'switch','model':'c3850','sn':'001','os':'ios','version':'15.0'}
  15. In [14]: D.get_or_create(**data2)
  16. Out[14]: (<Devices: test-sw-02>, True)
  17. In [16]: D
  18. Out[16]: <QuerySet [<Devices: test-sw-01>, <Devices: test-sw-02>]>
复制

7.2.2 删除删除

数据库表中的数据(偷偷增加了一台设备):

  1. In [1]: from hello.models import Devices
  2. # 删除一条记录
  3. # 第一种方法:get
  4. In [4]: D = Devices.objects.get(device_name = 'test-sw-02')
  5. In [5]: D.delete()
  6. Out[5]: (1, {'hello.Devices': 1})
  7. # 第二种方法:filter
  8. In [2]: Devices.objects.filter(device_name='test-sw-03').delete()
  9. Out[2]: (1, {'hello.Devices': 1})
  10. # 先还原数据,再删除所有的记录
  11. In [5]: Devices.objects.all().delete()
  12. Out[5]: (3, {'hello.Devices': 3})
复制

7.2.3 修改数据

  1. # 第一种方法:
  2. In [2]: D = Devices.objects.get(device_name='test-sw-03')
  3. In [3]: D.device_name = 'test-sw-13'
  4. In [4]: D.save()
  5. In [5]: Devices.objects.all()
  6. Out[5]: <QuerySet [<Devices: test-sw-01>, <Devices: test-sw-02>, <Devices: test-sw-13>]>
  7. # 第二种方法:
  8. # 指定字段更新,偷偷去看下后台的ID是多少
  9. In [6]: Devices.objects.filter(id=11)
  10. Out[6]: <QuerySet [<Devices: test-sw-13>]>
  11. In [7]: Devices.objects.filter(id=11).update(device_name='test-sw-03')
  12. Out[7]: 1
  13. In [8]: Devices.objects.get(device_name='test-sw-03')
  14. Out[8]: <Devices: test-sw-03>
  15. # 多个字段更新
  16. In [26]: data = {'vendor':'huawei','device_type':'switch','model':'S9303','sn':'001','os':'VRP'}
  17. In [27]: Devices.objects.filter(id=11).update(**data)
  18. Out[27]: 1
复制

最终效果如下(通过数据库查询):

7.2.4 查看数据

  • 查询多条数据

    列表嵌套一个字典(QuerySet对象)

    1. # 查询所有
    2. In [30]: D = Devices.objects.all()
    3. In [31]: D
    4. Out[31]: <QuerySet [<Devices: test-sw-01>, <Devices: test-sw-02>, <Devices: test-sw-03>]>
    5. # 每个对象及对象的属性
    6. In [32]: D[0]
    7. Out[32]: <Devices: test-sw-01>
    8. In [33]: D[0].device_name
    9. Out[33]: 'test-sw-01'
    10. # 切片,不支持负索引
    11. In [34]: D[:2]
    12. Out[34]: <QuerySet [<Devices: test-sw-01>, <Devices: test-sw-02>]>
    13. # 遍历
    14. In [36]: for d in D:
    15. ...: print(d.device_name)
    16. ...:
    17. test-sw-01
    18. test-sw-02
    19. test-sw-03
    20. # 返回指定的字段(values_list 和 values
    21. In [37]: D.values_list('device_name','ip')
    22. Out[37]: <QuerySet [('test-sw-01', '192.168.1.1'), ('test-sw-02', '192.168.1.2'), ('test-sw-03', '192.168.1.3')]>
    23. In [39]: D.values('device_name','vendor')
    24. Out[39]: <QuerySet [{'device_name': 'test-sw-01', 'vendor': 'cisco'}, {'device_name': 'test-sw-02', 'vendor': 'cisco'}, {'device_name': 'test-sw-03', 'vendor': 'huawei'}]>
    复制
  • 查询一条数据

    1. # 第一种方法:
    2. In [2]: D = Devices.objects.get(device_name='test-sw-01')
    3. In [3]: D
    4. # 返回的是一个对象
    5. Out[3]: <Devices: test-sw-01>
    6. # 取对象的属性值
    7. In [4]: D.device_name
    8. Out[4]: 'test-sw-01'
    9. In [5]: D.vendor
    10. Out[5]: 'cisco
    11. # 第二种方法:
    12. In [6]: data = {'device_name':'test-sw-01'}
    13. In [7]: D = Devices.objects.get(**data)
    14. In [8]: D.device_name
    15. Out[8]: 'test-sw-01'
    复制
    • 过滤查询
    1. In [9]: Devices.objects.filter(device_name='test-sw-01')
    2. Out[9]: <QuerySet [<Devices: test-sw-01>]>
    3. In [11]: Devices.objects.filter(**data)
    4. Out[11]: <QuerySet [<Devices: test-sw-01>]>
    复制
    • 过滤常用方法:
    1. # 不区分大小写:<属性值>__iexact
    2. In [16]: Devices.objects.filter(device_name__iexact='test-sw-01')
    3. Out[16]: <QuerySet [<Devices: test-sw-01>]>
    4. # 包含匹配:<属性值>__contains
    5. In [17]: Devices.objects.filter(device_name__contains='sw')
    6. Out[17]: <QuerySet [<Devices: test-sw-01>, <Devices: test-sw-02>, <Devices: test-sw-03>]>
    7. # 模糊匹配,不分区大小写:<属性值>__icontains
    8. In [18]: Devices.objects.filter(device_name__icontains='sw')
    9. Out[18]: <QuerySet [<Devices: test-sw-01>, <Devices: test-sw-02>, <Devices: test-sw-03>]>
    10. # 正则模糊匹配:<属性值>__regex
    11. In [20]: Devices.objects.filter(device_name__regex='-03$')
    12. Out[20]: <QuerySet [<Devices: test-sw-03>]>
    13. # 正则模糊匹配,不区分大小写:<属性值>__regex
    14. In [21]: Devices.objects.filter(device_name__iregex='^test')
    15. Out[21]: <QuerySet [<Devices: test-sw-01>, <Devices: test-sw-02>, <Devices: test-sw-03>]>
    16. # 排除过滤:<属性值>__contains
    17. In [22]: Devices.objects.exclude(device_name__contains='test-sw-01')
    18. Out[22]: <QuerySet [<Devices: test-sw-02>, <Devices: test-sw-03>]>
    19. # 包含带有sw的device_name,但排除了vendor是cisco厂商的
    20. In [23]: Devices.objects.filter(device_name__contains='sw').exclude(vendor='cisco')
    21. Out[23]: <QuerySet [<Devices: test-sw-03>]>
    22. # filter其他常用过滤查询方法
    23. __exact:精确匹配
    24. __iexact:精确匹配,忽略大小写
    25. __gt:大于
    26. __gte:大于等于
    27. __lt:小于
    28. __lte:小于等于
    29. __in:在一个list列表范围内
    30. __startswith:以...开头
    31. __startswith:以...开头,忽略大小写
    32. __endswith:以...结尾
    33. __range:在...范围内
    34. __year:日期的年份
    35. __month:日期的月份
    36. __day:日期的日数
    37. __isnull=True/False:字段是否为空
    复制

    get 和 filter的区别:

    1. # 都可以获取到指定的对象;
    2. # get是获取唯一数据的场景,数据不存在会报错;
    3. # filter适用于任何场景,返回是一个QuerySet对象,数据不存在则返回是空的对象。
    复制
    • 排序查询

      1. # 正序
      2. In [32]: Devices.objects.all().order_by('device_name')
      3. Out[32]: <QuerySet [<Devices: test-sw-01>, <Devices: test-sw-02>, <Devices: test-sw-03>]>
      4. # 倒序,前面加
      5. In [33]: Devices.objects.all().order_by('-device_name')
      6. Out[33]: <QuerySet [<Devices: test-sw-03>, <Devices: test-sw-02>, <Devices: test-sw-01>]>
      复制

8. 打通MTV

8.1 创建模型

参见以上的hello/models.py的配置。

8.2 创建视图view

  1. from django.shortcuts import render
  2. from hello.models import Devices
  3. def devicelist(request):
  4. # 对象实例化
  5. devices = Devices.objects.all()
  6. # {'devices':devices}表示传参
  7. return render(request, 'hello/device.html', {'devices':devices})
复制

8.3 创建模板

  1. <!--继承母版-->
  2. {% extends "base.html" %}
  3. <!--重写title的内容-->
  4. {% block title %}设备列表{% endblock %}
  5. <!--重写body的内容-->
  6. {% block body %}
  7. <p style="background-color: #77ee77">设备列表</p>
  8. <!--表格-->
  9. <table border="1">
  10. <!-- 表头-->
  11. <thead style="background-color: #00aced" >
  12. <tr>
  13. <td>设备名称</td>
  14. <td>IP地址</td>
  15. <td>厂商</td>
  16. <td>设备类型</td>
  17. <td>型号</td>
  18. <td>序列号</td>
  19. <td>操作系统</td>
  20. <td>版本号</td>
  21. </tr>
  22. </thead>
  23. <!--表的正文-->
  24. <tbody>
  25. {% for device in devices %}
  26. <tr>
  27. <td> {{ device.device_name }} </td>
  28. <td> {{ device.ip }} </td>
  29. <td> {{ device.vendor }} </td>
  30. <td> {{ device.device_type }} </td>
  31. <td> {{ device.model }} </td>
  32. <td> {{ device.sn }} </td>
  33. <td> {{ device.os }} </td>
  34. <td> {{ device.version }} </td>
  35. </tr>
  36. {% endfor %}
  37. </tbody>
  38. </table>
  39. {% endblock%}
复制

8.4 创建路由视图URL

  1. from django.urls import path
  2. from hello import view
  3. app_name = 'hello'
  4. urlpatterns = [
  5. path('devicelist', view.devicelist, name='devicelist'),
  6. ]
复制

8.5 效果图如下:

大家先不要在意前端效果,后面的项目,再把UI这块优化好,先到这里了,大家学会了吗?

 

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载