监控的目的
报告系统运行状况:
— 每一部分必须同时监控
— 内容包括吞吐量、反应时间、使用率等
提前发现问题
— 进行服务器性能调整前,知道调整什么
— 找出系统的瓶颈在什么地方
监控的资源类别
公开数据
— web、ftp、ssh、数据库等应用服务
— tcp或udp端口
私有数据
— cpu、内存、磁盘、网卡流量等使用信息
— 用户、进程等运行信息
常用系统监控命令:
[root@zabbix ~]# free -m //查看内存信息
[root@zabbix ~]# df -h //查看磁盘挂载信息
[root@zabbix ~]# swapon -s //查看交换分区
[root@zabbix ~]# iostat //查看磁盘信息
[root@zabbix ~]# uptime //查看cpu负载
[root@zabbix ~]# ifconfig //查看网卡信息
[root@zabbix ~]# netstat -ntulap //查看端口信息
[root@zabbix ~]# ping //查看网络连接信息
[root@zabbix ~]# ps aux //查看进程信息
自动化监控系统
Zabbix简介
监控服务器
— 监控服务器可以通过snmp或agent采集数据
— 数据可以写入mysql、oracle等数据库
— 服务器使用lnmp实现web前端的管理
被监控主机
— 被监控主机需要安装agent
— 常见的网络设备一般支持snmp
一、部署zabbix
1 服务端部署LNMP环境
[root@zabbix ~]# yum -y install gcc pcre-devel openssl-devel zlib-devel //安装依赖包
[root@zabbix ~]# ls
anaconda-ks.cfg
php-bcmath-5.4.16-42.el7.x86_64.rpm
initial-setup-ks.cfg
php-fpm-5.4.16-42.el7.x86_64.rpm
libevent-devel-2.0.21-4.el7.x86_64.rpm
php-mbstring-5.4.16-42.el7.x86_64.rpm
nginx-1.12.2.tar.gz
zabbix.tar.gz
[root@zabbix ~]# tar -xf nginx-1.12.2.tar.gz
[root@zabbix ~]# cd nginx-1.12.2/
[root@zabbix nginx-1.12.2]# ./configure --with-http_ssl_module
[root@zabbix nginx-1.12.2]# make
[root@zabbix nginx-1.12.2]# make install
[root@zabbix nginx-1.12.2]# ls /usr/local/nginx/
conf html logs sbin
[root@zabbix nginx-1.12.2]# yum -y install php php-mysql mariadb
[root@zabbix nginx-1.12.2]# yum -y install mariadb-server mariadb-devel
[root@zabbix nginx-1.12.2]# cd ..
[root@zabbix ~]# yum -y install php-fpm-5.4.16-42.el7.x86_64.rpm
#检查安装环境
[root@zabbix ~]# rpm -q php php-mysql mariadb mariadb-server
php-5.4.16-42.el7.x86_64
php-mysql-5.4.16-42.el7.x86_64
mariadb-5.5.56-2.el7.x86_64
mariadb-server-5.5.56-2.el7.x86_64
[root@zabbix ~]# rpm -q php-fpm
php-fpm-5.4.16-42.el7.x86_64
[root@zabbix ~]# rpm -q mariadb-devel
mariadb-devel-5.5.56-2.el7.x86_64
[root@zabbix ~]# ls /usr/local/nginx/
conf html logs sbin
2 配置nginx
[root@zabbix ~]# vim /usr/local/nginx/conf/nginx.conf
17 http {
18 fastcgi_buffers 8 16k; #缓存php生成的页面内容,8个16k
19 fastcgi_buffer_size 32k; #缓存php生产的头部信息
20 fastcgi_connect_timeout 300; #连接PHP的超时时间
21 fastcgi_send_timeout 300; #发送请求的超时时间
22 fastcgi_read_timeout 300; #读取请求的超时时间
65 location ~ \.php$ { #开启解释php代码
66 root html;
67 fastcgi_pass 127.0.0.1:9000;
68 fastcgi_index index.php;
69 # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
70 include fastcgi.conf
71 }
[root@zabbix ~]# /usr/local/nginx/sbin/nginx -t //检查配置文件是否修改正确
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
3 开启服务
[root@zabbix ~]# systemctl start mariadb
[root@zabbix ~]# netstat -ntulp| grep :3306
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 9099/mysqld
[root@zabbix ~]# systemctl start php-fpm
[root@zabbix ~]# netstat -ntulp| grep :9000
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 9157/php-fpm: maste
[root@zabbix ~]# /usr/local/nginx/sbin/nginx
[root@zabbix ~]# netstat -ntulp| grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 9167/nginx: master
4 测试php页面
[root@zabbix ~]# vim /usr/local/nginx/html/test.php
[root@zabbix ~]# curl http://localhost/test.php
33
5 安装zabbix源码
[root@zabbix ~]# yum -y install libevent-devel-2.0.21-4.el7.x86_64.rpm
[root@zabbix ~]# yum -y install net-snmp-devel curl-devel
[root@zabbix ~]# tar -xf zabbix-3.4.4.tar.gz
[root@zabbix ~]# cd zabbix-3.4.4/
[root@zabbix zabbix-3.4.4]# ./configure --enable-server --enable-proxy \
--enable-agent --with-mysql=/usr/bin/mysql_config \
--with-net-snmp --with-libcurl
[root@zabbix zabbix-3.4.4]# make install
[root@zabbix zabbix-3.4.4]# ls /usr/local/etc/ //查看配置文件
zabbix_agentd.conf zabbix_proxy.conf zabbix_server.conf
zabbix_agentd.conf.d zabbix_proxy.conf.d zabbix_server.conf.d
[root@zabbix zabbix-3.4.4]# ls /usr/local/bin/ //查看命令
zabbix_get zabbix_sender
6 初始化zabbix
[root@zabbix zabbix-3.4.4]# mysql
MariaDB [(none)]> creat database zabbix character set utf8;
MariaDB [(none)]> grant all on zabbix.* to zabbix@'localhost' identified by 'zabbix';
[root@zabbix zabbix-3.4.4]# cd database/
[root@zabbix database]# ls
ibm_db2 Makefile Makefile.am Makefile.in mysql oracle postgresql sqlite3
[root@zabbix mysql]# mysql -uzabbix -pzabbix zabbix
MariaDB [zabbix]> show tables;
[root@zabbix mysql]# cd ../..
[root@zabbix zabbix-3.4.4]# cp -a frontends/php/* /usr/local/nginx/html/
[root@zabbix zabbix-3.4.4]# chmod -R 777 /usr/local/nginx/html
7 修改配置文件,启动服务
[root@zabbix zabbix-3.4.4]# vim /usr/local/etc/zabbix_server.conf //修改监控服务端配置文件
38 LogFile=/tmp/zabbix_server.log //日志文件
85 DBHost=localhost //数据库主机(本机)
95 DBName=zabbix //设置数据库名称
111 DBUser=zabbix //设置数据库账户
119 DBPassword=zabbix //设置数据库密码
[root@zabbix zabbix-3.4.4]# useradd zabbix
[root@zabbix zabbix-3.4.4]# zabbix_server
[root@zabbix zabbix-3.4.4]# netstat -ntulp |grep :10051
tcp 0 0 0.0.0.0:10051 0.0.0.0:* LISTEN 19134/zabbix_server
[root@zabbix zabbix-3.4.4]# vim /usr/local/etc/zabbix_agentd.conf //修改i监控客户端配置文件(这里指本机)
30 LogFile=/tmp/zabbix_agentd.log //设置日志文件
93 Server=127.0.0.1, 192.168.2.55 //主动监控服务器IP
134 ServerActive=127.0.0.1:10051 //监控服务器ip地址端口号
145 Hostname=Zabbix server //设置本机主机名
280 UnsafeUserParameters=1``` //启用自定义key
[root@zabbix zabbix-3.4.4]# zabbix_agentd
[root@zabbix zabbix-3.4.4]# netstat -ntulp |grep :10050
tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 22395/zabbix_agentd
8 初始化访问zabbix监控页面
第二步检查配置环境时报错,根据错误提示修改相应配置文件,并安装依赖包
[root@zabbix zabbix-3.4.4]# vim /etc/php.ini
384 max_execution_time = 300 //最大执行时间
394 max_input_time = 300 //服务器接收数据的时间限制
672 post_max_size = 16M //POST数据最大容量
878 date.timezone = Asia/Shanghai //设置时区
[root@zabbix zabbix-3.4.4]# systemctl restart php-fpm
[root@zabbix ~]# yum -y install php-bcmath-5.4.16-42.el7.x86_64.rpm
[root@zabbix ~]# yum -y install php-mbstring-5.4.16-42.el7.x86_64.rpm
[root@zabbix ~]# yum -y install php-gd php-xml php-ldap
[root@zabbix ~]# systemctl restart php-fpm
[root@zabbix ~]# ls /usr/local/nginx/html/conf/zabbix.conf.php //安装完成后的配置文件
/usr/local/nginx/html/conf/zabbix.conf.php
初始登录用户名和密码:admin,zabbix
登录后,修改管理员密码和语言
基本使用:
(1)查看监控模板(配置—>模板)
(2)查看已监控的主机(配置—>主机—>启用)
(3)查看监控信息(监测中—>最新数据—>主机—>zabbix server)
9 配置zabbix监控服务(监控web33和web44主机)
(1)安裝zabbix客戶端zabbix_agentd
[root@web33 ~]# yum -y install httpd //以web33主机为例
[root@web33 ~]# echo web33 > /var/www/html/test.html
[root@web33 ~]# systemctl start httpd
[root@web33 ~]# curl http://localhost/test.html
[root@web33 ~]# vim mount_zabbix.sh
#!/bin/bash
useradd -s /sbin/nologin zabbix
yum -y install gcc pcre-devel
tar -xf zabbix-3.4.4.tar.gz
cd zabbix-3.4.4/
./configure --enable-agent
make && make install
[root@web33 ~]# ./mount_zabbix.sh //安装zabbix源码包
[root@web33 ~]# ls /usr/local/sbin/
zabbix_agentd
[root@web33 ~]# ls /usr/local/etc/
zabbix_agentd.conf zabbix_agentd.conf.d
[root@web33 ~]# vim /usr/local/etc/zabbix_agentd.conf //修改配置文件
30 LogFile=/tmp/zabbix_agentd.log
93 Server=127.0.0.1, 192.168.2.55 //允许哪些主机监控本机
134 ServerActive=192.168.2.55:10051 //监控服务器ip和端口
145 Hostname=web33 //被监控主机的名称
280 UnsafeUserParameters=1 //允许自定义监控脚本
[root@web33 ~]# zabbix_agentd
[root@web33 ~]# netstat -ntulp |grep :10050
tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 20859/zabbix_agentd
(2)监控网站服务器web33和web44
访问http://192.168.2.55/index.php
a. 配置 —>主机—>创建主机—>主机名称、可见的名称、群组、ip地址—>模板—>链接指示器:选择相应模板,添加
b. 配置—>主机—>可用性
(3)自定义监控命令
[root@web33 ~]# sed -n '280p' /usr/local/etc/zabbix_agentd.conf
UnsafeUserParameters=1
[root@web33 ~]# grep -n 'Include' /usr/local/etc/zabbix_agentd.conf
255:### Option: Include
261:# Include=
263:# Include=/usr/local/etc/zabbix_agentd.userparams.conf
264:# Include=/usr/local/etc/zabbix_agentd.conf.d/
265:# Include=/usr/local/etc/zabbix_agentd.conf.d/*.conf
[root@web33 ~]# sed -i '265s/^#//' /usr/local/etc/zabbix_agentd.conf //去掉265行注释
[root@web33 ~]# grep -n 'Include' /usr/local/etc/zabbix_agentd.conf
255:### Option: Include
261:# Include=
263:# Include=/usr/local/etc/zabbix_agentd.userparams.conf
264:# Include=/usr/local/etc/zabbix_agentd.conf.d/
265: Include=/usr/local/etc/zabbix_agentd.conf.d/*.conf
########################################################################
[root@web33 ~]# vim /usr/local/etc/zabbix_agentd.conf
265 Include=/usr/local/etc/zabbix_agentd.conf.d/*.conf //自定义监控配置文件
280 UnsafeUserParameters=1 //开启自定义监控
[root@web33 ~]# wc -l /etc/passwd |awk '{print $1}' //统计用户数
42
[root@web33 ~]# vim /usr/local/etc/zabbix_agentd.conf.d/get_sum_users.conf
UserParameter=getusers,wc -l /etc/passwd |awk '{print $1}' //自定义监控格式:命令名,命令
[root@web33 ~]# killall -9 zabbix_agentd //杀死进程
[root@web33 ~]# killall -9 zabbix_agentd
zabbix_agentd: no process found
[root@web33 ~]# zabbix_agentd //重启zabbix_agentd服务
[root@web33 ~]# netstat -ntulp |grep :10050
tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 5300/zabbix_agentd
[root@web33 ~]# zabbix_get -s 127.0.0.1 -p 10050 -k getusers //测本机试自定义监控命令
42
[root@zabbix ~]# zabbix_get -s 192.168.2.33 -p 10050 -k getusers //监控服务器远程测试被监控端自定义命令
42
(4)登陆管理页面配置自定义监控、
10、zabbix报警配置
概念介绍
(1)创建触发器:配置—>模板—>选择对应模板中触发器—>创建触发器
—>表达式:添加—>选择监控项,设置功能—>底部添加
(2)指定触发器触发后要执行的动作方式(这里选择发送邮件的方式):管理—>报警媒介类型—>Email—>配置后点击更新
检查本机邮件服务器25端口是否开启
[root@zabbix ~]# netstat -ntulp |grep :25
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1124/master
tcp6 0 0 ::1:25 :::* LISTEN 1124/master
若没有25端口,则需要安装并启动postfix
[root@zabbix ~]# yum -y install postfix
[root@zabbix ~]# systemctl start postfix
[root@zabbix ~]# systemctl enable postfix
测试给本机给zabbix用户发送邮件
[root@zabbix ~]# mail -s "testmail" zabbix < /etc/hosts
[root@zabbix ~]# mail -u zabbix
Heirloom Mail version 12.5 7/5/10. Type ? for help.
"/var/mail/zabbix": 1 message
> 1 root Thu May 23 21:35 20/750 "testmail"
(3)为账户添加Media(指定收件人邮箱)
管理—>用户—>Admin—>报警媒介—>添加—>收件人:zabbix@localhost—>添加—>更新
(4)创建执行动作
配置—>动作—>事件源选择触发器,创建动作—>动作:定义名称(dongzuo1),新的触发条件选择触发器,选择web33: chufaqi1_web33_users,添加—>操作:默认接收人(定义标题),点击“新的”,发送到用户:添加Admin,仅送到Email,点击小字体“添加”,最后点击最下方添加
(5)测试触发器,发送报警邮件
[root@web33 ~]# useradd tom1
[root@web33 ~]# useradd tom2
[root@web33 ~]# useradd tom3
##############################################################
[root@zabbix ~]# mail -u zabbix //查看邮件(收到报警邮件2)
Heirloom Mail version 12.5 7/5/10. Type ? for help.
"/var/mail/zabbix": 2 messages 1 new
1 root Thu May 23 21:35 20/750 "testmail"
>N 2 [email protected] Thu May 23 23:00 20/819 "big33"
& 2
Message 2:
From [email protected] Thu May 23 23:00:06 2019
Return-Path:
X-Original-To: zabbix@localhost
Delivered-To: [email protected]
From:
To:
Date: Thu, 23 May 2019 23:00:06 +0800
Subject: big33
Content-Type: text/plain; charset="UTF-8"
Status: R
Problem started at 23:00:03 on 2019.05.23
Problem name: chufaqi1_web33_users
Host: web33
Severity: Disaster
Original problem ID: 164
Django简介
• Django是一个开放源代码的Web应用框架,由Python写成
框架介绍
• Django 框架的核心组件有:
– 用于创建模型的对象关系映射
– 为最终用户设计的完美管理界面
– 一流的 URL 设计
– 设计者友好的模板语言
– 缓存系统
MTV模式
• Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同
– M 代表模型(Model):负责业务对象和数据库的关系映射(ORM)
– T 代表模板 (Template):负责如何把页面展示给用户(html)
– V 代表视图(View):负责业务逻辑,并在适当时候调用Model和Template
• 除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template
MTV响应模式
• Web服务器(中间件)收到一个http请求
• Django在URLconf里查找对应的视图(View)函数来处理http请求
• 视图函数调用相应的数据模型来存取数据、调用相应的模板向用户展示页面
• 视图函数处理结束后返回一个http的响应给Web服务器
• Web服务器将响应发送给客户端
虚拟环境
虚拟环境可以理解为就是一个目录,克隆python到这个目录,安装模块到虚拟环境,将来不用的时候,可以直接把虚拟环境的目录删除。
安装django
[root@room9pc01 exercise]# mkdir day17
[root@room9pc01 exercise]# cd day17
[root@room9pc01 day17]# ls
[root@room9pc01 day17]# python3 -m venv /opt/djenv/ //创建python虚拟环境目录
[root@room9pc01 day17]# ls /opt/djenv/
bin include lib lib64 pyvenv.cfg
[root@room9pc01 day17]# source /opt/djenv/bin/activate //激活python虚拟环境
(djenv) [root@room9pc01 day17]# cd /root/桌面/python/zzg_pypkgs/dj_pkgs
(djenv) [root@room9pc01 dj_pkgs]# ls
asn1crypto-0.24.0-py2.py3-none-any.whl
cffi-1.11.5-cp36-cp36m-manylinux1_x86_64.whl
cryptography-2.3.1-cp34-abi3-manylinux1_x86_64.whl
Django-1.11.6-py2.py3-none-any.whl
idna-2.7-py2.py3-none-any.whl
pycparser-2.18.tar.gz
PyMySQL-0.9.2-py2.py3-none-any.whl
pytz-2018.5-py2.py3-none-any.whl
six-1.11.0-py2.py3-none-any.whl
(djenv) [root@room9pc01 dj_pkgs]# pip install * //安装django
###########################################################################
(djenv) [root@room9pc01 dj_pkgs]# pip install django==1.11.6 //在线安装django
创建项目
• Djanog可以自动生成一些代码,这些代码创建一个Django项目:一个Django实例的设置集合,包括数据库的配置、Django有关的选项和应用有关的选项
(djenv) [root@room9pc01 dj_pkgs]# cd -
(djenv) [root@room9pc01 day17]# ls
(djenv) [root@room9pc01 day17]# django-admin startproject mysite //创建项目mysite
(djenv) [root@room9pc01 day17]# ls
mysite
(djenv) [root@room9pc01 day17]# tree mysite/
mysite/ # 项目的根目录
├── manage.py # 项目管理工具
└── mysite # 项目配置目录
├── __init__.py
├── settings.py # 配置文件
├── urls.py # 程序的入口文件 URLConf
└── wsgi.py # 将项目部署到Web服务器时应用
项目文件说明
• 外层的mysite/根目录仅仅是项目的一个容器。 它的名字与Django无关;可以将其重命名为你喜欢的任何内容
• manage.py:一个命令行工具,可以使用多种方式对Django项目进行交互。 可以在django-admin和manage.py中读到关于manage.py的所有细节
• 内层的mysite/目录是项目的真正的Python包。 它是导入任何东西时将需要使用的Python包的名字(例如 mysite.urls)
• mysite/init.py:一个空文件,它告诉Python这个目录应该被看做一个Python包
• mysite/settings.py:该Django 项目的设置/配置。Django settings 将告诉你这些设置如何工作。
• mysite/urls.py:此Django项目的URL声明;Django驱动的网站的“目录”
• mysite/wsgi.py:用于项目的与WSGI兼容的Web服务器入口
开发服务器
• Django自带一个开发服务器,默认运行于8000端口
• 该开发服务器不要应用在生产环境下
测试站点
(djenv) [root@room9pc01 day17]# cd mysite/
(djenv) [root@room9pc01 mysite]# python manage.py runserver //django提供了一个测试服务器,功能简单,不能用于生产环境
浏览器访问http://127.0.0.1:8000/
配置pycharm
(1)File -> Settings -> Project: day03 -> Project Interpreter -> 点右上角齿轮 -> add Local -> Existing environment (勾选Make available to all project) -> 点右侧… -> /opt/djenv/bin/python
(2)File -> Settings -> Languages & Frameworks -> django -> Enable django support -> django project root 填写外层mysite目录 -> settings 选择mysite/settings.py
配置项目数据库
(djenv) [root@room9pc01 mysite]# mysql -uroot -p123456
MariaDB [(none)]> CREATE DATABASE dj1812 DEFAULT CHARSET UTF8;
修改django设置
# mysite/settings.py(#开头表示配置该文件,下同)
28 ALLOWED_HOSTS = '*' //允许所有主机访问
77 DATABASES = { //数据库访问设置
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dj1812',
'USER': ' root'
'PASSWORD': '123456'
'HOST': '127.0.0.1'
'PORT': '3306'
}
}
111 LANGUAGE_CODE = 'zh-hans' //中文
113 TIME_ZONE = 'Asia/Shanghai' //上海时区
119 USE_TZ = False
############################################################################
# mysite/__init__.py
import pymysql
pymysql.install_as_MySQLdb()
############################################################################
(djenv) [root@room9pc01 mysite]# ls
db.sqlite3 manage.py mysite
(djenv) [root@room9pc01 mysite]# systemctl stop httpd
(djenv) [root@room9pc01 mysite]# python manage.py runserver 0:80
生成数据库
• Django生成的项目,使用了很多预先编写好的应用,这些应用需要用到数据
• 只要执行以下语句,即可自动生成数据库生成内建应用的表
(djenv) [root@room9pc01 mysite]# python manage.py makemigrations
(djenv) [root@room9pc01 mysite]# python manage.py migrate
(djenv) [root@room9pc01 mysite]# mysql -uroot -p123456
MariaDB [(none)]> use dj1812
MariaDB [dj1812]> show tables; #查看上一步生成的表
创建管理员账户
• 访问后台需要有超级用户身份
• 超级用户需要单独创建
• 用户将写到数据库中
(djenv) [root@room9pc01 mysite]# python manage.py createsuperuser
依次输入:管理员用户名(默认root),邮箱地址,密码(必须大于8个字符,且不能全为数字)
(djenv) [root@room9pc01 mysite]# python manage.py runserver 0:80
浏览器访问后台管理页面 :http://127.0.0.1/admin
创建应用
应用简介
• 应用是一个Web应用程序,它完成具体的事项 ——比如一个博客系统、一个存储公共档案的数据库或者一个简单的投票应用
• 项目是特定网站的配置和应用程序的集合
• 一个项目可以包含多个应用
• 一个应用可以运用到多个项目中去
创建应用
• 应用可以放在Python path上的任何位置
• 可以在manage.py文件同级目录创建应用,以便可以将它作为顶层模块导入,而不是mysite的子模块
案例:创建网页投票结果统计项目
(djenv) [root@room9pc01 mysite]# python manage.py startapp polls //创建应用polls
集成应用到项目
# mysite/settings.py
33 INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls', #激活应用polls
]
配置URLconf
• 为了整洁起见,用户与polls相关的url都交给polls应用进行路由
url规划
授权
# mysite/urls.py
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^polls/', include('polls.urls')),
]
一、创建首页
1、配置urll
# mysite/polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
# url(正则, 函数, name=该url的名字),
url(r'^$', views.index, name='index'), //正则匹配首页(http://127.0.0.1/polls/,后续所有网页的url配置均从http://127.0.0.1/polls/之后的字符开始匹配)
]
创建视图
• 视图是URLconf路由到某一URL时执行的函数
• 为上一步polls主页编写简单视图,编辑polls/views.py如下:
2、编写函数
# mysite/polls/views.py
from django.shortcuts import render
def index(request): //首页函数
return render(request, 'index.html')
函数至少需要有一个参数,用户的请求会传给该参数。返回值是通过render函数调用一个模板,将模板文件发送给用户。
3、创建模板文件index.html
(djenv) [root@room9pc01 polls]# mkdir templates //模板文件目录名必须为templates
(djenv) [root@room9pc01 polls]# ls
admin.py __init__.py models.py templates urls.py
#############################################################################
# mysite/polls/templates/index.html
投票首页
投票首页
4、测试
(djenv) [root@room9pc01 polls]# cd ..
(djenv) [root@room9pc01 mysite]# ls
db.sqlite3 manage.py mysite polls
(djenv) [root@room9pc01 mysite]# python manage.py runserver 0:80
浏览器访问http://127.0.0.1/出现404是正常的,因为确实没有定义;访问http://127.0.0.1/polls/才能显示应用的首页。
二、创建投票详情页
1、配置url
# mysite/polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
#url(正则,函数,name=该url的名字)
url(r'^$', views.index, name='index'), //正则匹配首页(http://127.0.0.1/polls/)
url(r'^(?P\d+)/$', views.detail, name='detail'), 正则匹配投票详情页(http://127.0.0.1/polls/num/,注num表示任意整数)
]
2、编写函数
# mysite/polls/views.py
from django.shortcuts import render
# Create your views here.
def index(request): //首页函数
return render(request, 'index.html')
def detail(request, question_id): //投票详情页函数
return render(request, 'detail.html', {'qid': question_id})
3、创建模板文件index.html
# mysite/polls/templates/detail.html
投票详情
{{ qid }}号投票详情
//{{ qid }}变量接收投票详情页函数传递过来的question_id的值
4、测试访问
(djenv) [root@room9pc01 mysite]# python manage.py runserver 0:80
浏览器访问http://127.0.0.1/polls/1/
三、创建投票结果页
1、配置url
from django.conf.urls import url
from . import views
urlpatterns = [
#url(正则,函数,name=该url的名字)
url(r'^$', views.index, name='index'), //正则匹配首页(http://127.0.0.1/polls/)
url(r'^(?P\d+)/$', views.detail, name='detail'), //正则匹配投票详情页(http://127.0.0.1/polls/num/)
url(r'^(?P\d+)/result/$', views.result, name='result'), //正则匹配投票结果页(http://127.0.0.1/polls/num/result/)
]
2、编写函数
# mysite/polls/views.py
from django.shortcuts import render
# Create your views here.
def index(request): //首页函数
return render(request, 'index.html')
def detail(request, question_id): //投票详情页函数
return render(request, 'detail.html', {'qid': question_id})
def result(request, question_id): //投票结果页函数
return render(request, 'result.html', {'qid': question_id})
四、django模型
模型理念
• 模型指出了数据的唯一、明确的真实来源
• 它包含了正在存储的数据的基本字段和行为
• Django遵循DRY(Do not Repeat Yourself) 原则
• 这个原则的目标是在一个地方定义你的数据模型,并自动从它获得需要的信息
模型说明
• 每个模型都用一个类表示,该类继承自django.db.models.Model
• 每个模型都有一些类变量,在模型中每个类变量都代表了数据库中的一个字段
• 每个字段通过Field类的一个实例表示 —— 例如字符字段CharField和日期字段DateTimeField。 这种方法告诉Django,每个字段中保存着什么类型的数据
• 每个Field 实例的名字就是字段的名字,并且是机器可读的格式
• 在Python代码中将使用到它的值,并且数据库将把它用作表的列名
本项目polls应用模型构思
ID | 内容 |
---|---|
1 | 期待的工资? |
2 | 希望进入的公司? |
(2)选项表:
ID | 内容 | 问题ID | 票数 |
---|---|---|---|
1 | 百度 | 2 | 0 |
5000-8000 | 1 | 0 | |
3 | 华为 | 2 | 0 |
> 10000 | 1 | 0 |
1.1、编写问题模型
# mysite/polls/models.py
from django.db import models
class Question(models.Model): //定义问题模型的类
question_text = models.CharField(max_length=200, unique=True, null=False)
pub_date = models.DateTimeField()
def __str__(self):
return '问题: %s' % self.question_text
1.2、生成问题表
迁移Django储存模型
• polls应用建立了新的模型,该模型需要反馈到数据库中
• 通过运行makemigrations告诉Django,已经对模型做了一些更改,并且会将这些更改记录为迁移文件
• 迁移文件位于polls/migrations/目录下
生成数据库
• makemigrations只是生成了迁移文件,并未真正的反馈到数据中
• migrate才是真正生成数据库
(djenv) [root@room9pc01 mysite]# python manage.py makemigrations
(djenv) [root@room9pc01 mysite]# python manage.py migrate
MariaDB [(none)]> use dj1812
MariaDB [dj1812]> show tables;
#会发现多了一个表:polls_question,命名规则为polls_类名(小写)
MariaDB [dj1812]> desc polls_question;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| question_text | varchar(200) | NO | UNI | NULL | |
| pub_date | datetime | NO | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
2.1、编写选项模型
#mysite/polls/models.py
from django.db import models
# Create your models here.
class Question(models.Model): //定义问题模型的类
question_text = models.CharField(max_length=200, unique=True, null=False)
pub_date =models.DateTimeField()
def __str__(self):
return '问题: %s' % self.question_text
class Choice(models.Model): //定义选项模型的类
choice_text = models.CharField(max_length=200, null=False)
votes = models.IntegerField(default=0)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
def __str__(self):
return '%s => %s' % (self.question, self.choice_text)
2.2、生成选项表
(djenv) [root@room9pc01 mysite]# python manage.py makemigrations
(djenv) [root@room9pc01 mysite]# python manage.py migrate
(djenv) [root@room9pc01 mysite]# mysql -uroot -p123456```
MariaDB [(none)]> use dj1812
MariaDB [dj1812]> show tables;
会发现多了一个表:polls_choice
MariaDB [dj1812]> desc polls_choice;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| choice_text | varchar(200) | NO | | NULL | |
| votes | int(11) | NO | | NULL | |
| q_id | int(11) | NO | MUL | NULL | |
+-------------+--------------+------+-----+---------+----------------+
因为Question和Choice是有主外键约束的,也就是说一个问题可以对应多个选项。但是一个选项只能对应一个问题。在Choice中,q是外键,数据库自动为它加上_id,成为外键字段,如果Choice中用的是question,那么外键字段的名字就是question_id。
将Choice类中的q改为question。完成之后更新数据库:
(djenv) [root@room9pc01 mysite]# python manage.py makemigrations
Did you rename choice.q to choice.question (a ForeignKey)? [y/N] y
(djenv) [root@room9pc01 mysite]# python manage.py migrate
MariaDB [dj1812]> desc polls_choice;
MariaDB [dj1812]> desc polls_choice;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| choice_text | varchar(200) | NO | | NULL | |
| votes | int(11) | NO | | NULL | |
| question_id | int(11) | NO | MUL | NULL | |
+-------------+--------------+------+-----+---------+----------------+
发现q_id变成了question_id
3、将模型注册到后台管理界面
注册管理后台
• 投票的问题和选项,可以通过后台进行录入、编辑
• 只要把模型注册到后台管理界面即可
# mysite/polls/admin.py
from django.contrib import admin
from .models import Question, Choice
# Register your models here.
admin.site.register(Question)
admin.site.register(Choice)
4、启动开发服务器
(djenv) [root@room9pc01 mysite]# python manage.py runserver 0:80
浏览器访问后台http://127.0.0.1/admin/,添加一些问题和选项,如下图所示:
接下一篇博客《python:django API、视图、模板和表单使用》
注:续上一篇博客《zabbix监控部署》
一、 自动发现
— 当Zabbix需要监控的设备越来越多,手动添加监控设备越来越有挑战,此时,可以考虑使用自动发现功能
— 需要批量一次性添加一组监控主机,也可以使用自动发现功能
1、配置自动发现规则:
配置—>自动发现—>创建发现规则—>规则名称,ip范围(192.168.2.100-254),更新间隔(设为1m)—>新的:检查类型—http,80端口—>添加
2、配置自动发现后触发的动作:
配置—>事件源:自动发现,创建动作—>动作:动作名称,ip范围(192.168.2.100-254),添加—>操作:新的,操作类型—添加主机到群组(webgrp),添加;新的,操作类型—与模板关联(Template App HTTP Service,Template OS Linux),添加,点击最下面的添加,完成动作创建
测试自动发现
开启两台虚拟机192.168.2.101和192.168.2.102,均开启httpd服务,安装并开启zabbix_agentd服务
一段时间后,zabbix监测到以上两台虚拟机的httpd和os系统服务,如下图所示:
二、主被动监控
主动和被动都是对被监控端主机而言的
zabbix默认采用的是被动监控
— 被动监控:Server向Agent发起连接,发送监控项(key),Agent接受请求,响应监控数据
— 主动监控:Agent向Server发起连接,Agent请求需要监测的监控项目列表,Server响应Agent发送一个items列表,Agent确认收到监控列表,tcp连接完成,绘画关闭,Agent开始周期性地收集数据
主动被动监控区别:
— Server不用每次需要数据都连接Agent,Agent会自己收集数据并处理数据,Server仅需要保存数据即可
当监控主机达到一定量级后,zabbix服务器会越来越慢,此时可以ikaolv使用主动监控,释放服务器压力
另外,zabbix也支持分布式监控,也是可以考虑的方案
1、配置主动监控(web102主机为例演示)
[root@web102 ~]# netstat -ntulp |grep 10050
tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 10947/zabbix_agentd
[root@web102 ~]#
[root@web102 ~]# killall -p zabbix_agentd //关闭zabbix_agent服务
[root@web102 ~]# killall -p zabbix_agentd
zabbix_agentd: no process found
[root@web102 ~]# netstat -ntulp |grep 10050
[root@web102 ~]# vim /usr/local/etc/zabbix_agentd.conf //修改配置文件
93 # Server=127.0.0.1, 192.168.2.55 //主动模式下,注释该行
118 StartAgents=0 //只启动agent进程,没有端口号
134 ServerActive=192.168.2.55 //允许监控本机的监控服务器ip,默认端口10051
145 Hostname=web102 //向Server发送连接时标示本机身份的主机名
183 RefreshActiveChecks=120 //主动连接Server的时间间隔(s)
280 # UnsafeUserParameters=1 //不启用自定义监控
[root@web102 ~]# zabbix_agentd //启动进程
[root@web102 ~]# netstat -ntulp |grep 10050 //主动模式下没有端口号
[root@web102 ~]# ps -C zabbix_agentd //主动模式下,仅有zabbix_agentd进程
PID TTY TIME CMD
9070 ? 00:00:00 zabbix_agentd
9071 ? 00:00:00 zabbix_agentd
9072 ? 00:00:00 zabbix_agentd
2、克隆模板,修改监控项模式
配置—>模板—>过滤器:linux,应用,选择Template OS Linux—>全克隆—>模板名称:A_Template OS Linux,添加—>选择克隆出来的A_Template OS Linux模板下的监控项—>选中所有监控项,批量更新—>类型:Zabbix客户端(主动式),更新—>禁用类型中不支持主动式的监控项
3、添加监控主机
配置—>主机—>创建主机—>主机名称:web102,可见的名称:web102,群组:Linux servers,ip地址:0.0.0.0,端口:0—>模板,链接指示器:A_Template OS Linux,依次点击上下的添加按钮
4、查看监测数据
方式1:监测中—>最新数据:过滤web102主机
方式2:监测中—>图形:群组,主机,图形
三、拓扑图与聚合图形
1、拓扑图:绘制拓扑图可以快速了解服务器架构
监测中—>拓扑图,创建拓扑图—>名称:web,添加—>选择web—>编辑拓扑图—>图标:添加—>双击图标,修改图标样式:标签,图标—>ctrl+要连接的两台主机—>链接:添加
拓扑图效果如下:
2、聚合图形:在一个页面显示多个数据图标,方便了解多组数据
监测中—>聚合图形—>名称:juhetu1,设置列数和行数,添加—>聚合图形后面的构造函数—>更改—>图形:选择,监控主机,监控项—>设置图形宽度和高度,对齐位置—>添加
添加完4张监控图的效果如下:
四、利用脚本自定义监控命令
监控案例一:利用监控脚本自定义监控nginx状态
1、准备虚拟机(192.168.2.200)环境
[root@web200 ~]# ls
anaconda-ks.cfg
nginx-1.12.2.tar.gz
mount_zabbix.sh
initial-setup-ks.cfg
zabbix-3.4.4.tar.gz
[root@web200 ~]# ./mount_zabbix.sh //利用脚本安装zabbix
[root@web200 ~]# tar -xf nginx-1.12.2.tar.gz
[root@web200 ~]# cd nginx-1.12.2/
[root@web200 nginx-1.12.2]# yum -y install zlib-devel //安装依赖包
[root@web200 nginx-1.12.2]# ./configure --with-http_stub_status_module //配置nginx,加载状态模块
[root@web200 nginx-1.12.2]# make && make install
[root@web200 nginx-1.12.2]# vim /usr/local/nginx/conf/nginx.conf
...
35 server {
36 location /status {
37 stub_status on; //启用状态模块
38 }
39 listen 80;
40 server_name localhost;
...
[root@web200 nginx-1.12.2]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@web200 nginx-1.12.2]# /usr/local/nginx/sbin/nginx
[root@web200 nginx-1.12.2]# netstat -ntulp |grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 14937/nginx: master
[root@web200 nginx-1.12.2]# curl http://192.168.2.200/status //查看nginx状态
Active connections: 1 //实时连接数量
server accepts handled requests
1 1 1 //三个数字分别表示历史连接总数、处理的连接数量、处理的请求数量
Reading: 0 Writing: 1 Waiting: 0 //依次为读处理数量、写处理数量、等待处理数量
2、编写监控脚本
[root@web200 nginx-1.12.2]# vim /usr/local/bin/nginx_status.sh
#!/bin/bash
case $1 in
active)
curl -s http://127.0.0.1/status |awk '/Active/{print $NF}';; //NF为awk内置变量,记录当前处理行的字段个数(列数)
waiting)
curl -s http://127.0.0.1/status |awk '/Waiting/{print $NF}';;
accepts)
curl -s http://127.0.0.1/status |awk 'NR==3{print $2}';; //NF为awk内置变量,记录当前已读入行的数量(行数)
esac
[root@web200 nginx-1.12.2]# chmod +x /usr/local/bin/nginx_status.sh
[root@web200 nginx-1.12.2]# /usr/local/bin/nginx_status.sh active //测试脚本执行情况
1
[root@web200 nginx-1.12.2]# /usr/local/bin/nginx_status.sh waiting
0
[root@web200 nginx-1.12.2]# /usr/local/bin/nginx_status.sh accepts
14
3、利用监控脚本自定义监控命令
[root@web200 nginx-1.12.2]# vim /usr/local/etc/zabbix_agentd.conf
93 Server=127.0.0.1, 192.168.2.55
134 ServerActive=192.168.2.55:10051
145 Hostname=web33
265 Include=/usr/local/etc/zabbix_agentd.conf.d/*.conf
280 UnsafeUserParameters=1
[root@web200 nginx-1.12.2]# vim /usr/local/etc/zabbix_agentd.conf.d/nginx_status.conf //创建自定义监控命令
UserParameter=nginx.status[*],/usr/local/bin/nginx_status.sh $1 //监控命令nginx.status[*]匹配脚本传递的参数
[root@web200 nginx-1.12.2]# zabbix_agentd //启动zabbix_agent服务
[root@web200 nginx-1.12.2]# netstat -ntulp |grep :10050
tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 16827/zabbix_agentd
[root@web200 nginx-1.12.2]# zabbix_get -s 127.0.0.1 -p 10050 -k nginx.status[active] //本机测试自定义监控命令
1
[root@web200 nginx-1.12.2]# zabbix_get -s 127.0.0.1 -p 10050 -k nginx.status[waiting]
0
[root@web200 nginx-1.12.2]# zabbix_get -s 127.0.0.1 -p 10050 -k nginx.status[accepts]
16
[root@zabbix ~]# zabbix_get -s 192.168.2.200 -p 10050 -k nginx.status[accepts] //监控服务器测试200主机的自定义监控命令
18
[root@zabbix ~]# zabbix_get -s 192.168.2.200 -p 10050 -k nginx.status[active]
1
[root@zabbix ~]# zabbix_get -s 192.168.2.200 -p 10050 -k nginx.status[waiting]
0
4、登陆zabbix监控页面配置自定义监控
配置—>模板—>模板名称和可见的名称:B_nginx,群组:webgrp—>添加—>选择B_nginx模板下的应用集—>创建应用集—>名称:nginx,添加—>选择应用集nginx后面的监控项—>创建监控项(键值绑定自定义监控命令)—>名称:active,键值:nginx.status[active],应用集:nginx,选择底部添加,继续创建另外两个监控项nginx.status[waiting]和nginx.status[accepts]
5、调用自定义监控模板监控web200主机
配置—>主机—>创建主机,主机名称和可见的名称:web200,群组:webgrp,ip地址:192.168.2.200,端口:10050—>模板,链接指示器:B_nginx,依次点击上下的添加按钮
6、查看web200主机监控情况
监测中—>最新数据—>过滤选择web200主机,应用—>获取最新数据
监控案例二:利用脚本自定义监控web200主机TCP网络连接状态
1、编写监控脚本
[root@web200 nginx-1.12.2]# vim /usr/local/bin/net_status.sh
#!/bin/bash
case $i in
estab)
ss -antp | awk '/^ESTAB/{x++} END{print x}';;
close_wait)
ss -antp | awk '/^CLOSE-WAIT/{x++} END{print x}';;
time_wait)
ss -antp | awk '/^TIME-WAIT/{x++} END{print x}';;
esac
[root@web200 nginx-1.12.2]# chmod +x /usr/local/bin/net_status.sh
[root@web200 nginx-1.12.2]# /usr/local/bin/net_status.sh estab //测试监控脚本运行情况
1
[root@web200 nginx-1.12.2]# /usr/local/bin/net_status.sh close_wait
[root@web200 nginx-1.12.2]# /usr/local/bin/net_status.sh time_wait
12
2、自定义监控命令,重启服务
[root@web200 nginx-1.12.2]# vim /usr/local/etc/zabbix_agentd.conf.d/nginx_status.conf //在案例一自定义监控配置文件基础上添加监控命令
UserParameter=nginx.status[*],/usr/local/bin/nginx_status.sh $1
UserParameter=net.status[*],/usr/local/bin/net_status.sh $1
[root@web200 nginx-1.12.2]# killall -9 zabbix_agentd
[root@web200 nginx-1.12.2]# killall -9 zabbix_agentd
zabbix_agentd: no process found
[root@web200 nginx-1.12.2]# zabbix_agentd
[root@web200 nginx-1.12.2]# netstat -ntulp | grep :10050
tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 24029/zabbix_agentd
[root@web200 nginx-1.12.2]# zabbix_get -s 127.0.0.1 -p 10050 -k net.status[close_wait] //zabbix_agent测试自定义监控命令
[root@web200 nginx-1.12.2]# zabbix_get -s 127.0.0.1 -p 10050 -k net.status[time_wait]
13
[root@web200 nginx-1.12.2]# zabbix_get -s 127.0.0.1 -p 10050 -k net.status[estab]
3
[root@zabbix ~]# zabbix_get -s 192.168.2.200 -p 10050 -k net.status[estab] //监控服务器测试脚本自定义监控命令
2
[root@zabbix ~]# zabbix_get -s 192.168.2.200 -p 10050 -k net.status[close_wait] //无数据输出,监控页面该监控项会显示灰色
[root@zabbix ~]# zabbix_get -s 192.168.2.200 -p 10050 -k net.status[time_wait]
14
3、在已有模板基础上创建应用集和监控项
配置—>模板—>B_nginx,应用集—>创建应用集—>名称:net—>监控项—>创建监控项—>名称:net_estab,键值(绑定自定义监控命令):net.status[estab],应用集:net,点击底部添加,继续创建另外两个监控项net_close_wait和net_time_wait
五、常见监控需求
1、mysql
2、NoSQL数据库(数据库状态)
3、php-fpm:并发、队列、进程数量等
4、tomcat服务器状态
5、硬件设备(交换机、路由等,一般通过snmp协议监控)
注:续上一篇博客《python:django部署》
在python shell中运行指令
(djenv) [root@room9pc01 mysite]# python manage.py shell
Python 3.6.7 (default, May 20 2019, 13:24:03)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
导入前面编写的模型
>>> from polls.models import Question, Choice
创建问题实例
>>> q1 = Question(question_text='你期待哪家公司给你发offer?', pub_date='2019-05-27 9:00:00')
>>> q1.save()
使用objects管理器
django为每一个ORM类都创建了名为objects的管理器,可以通过这个管理器的方法实现对表的管理。
>>> q2 = Question.objects.create(question_text='从学校毕业后,你希望去哪个城市工作?', pub_date='2019-06-01 12:00:00')
创建选项实例
c1 = Choice(choice_text='腾讯', question=q1) //由于存在外键关系,django通过Question对象可以反向得到Choice对象集
>>> c1.save()
使用管理器创建选项实例
>>> c2 = Choice.objects.create(choice_text='华为', question=q1)
通过问题实例的管理器创建选项
问题和选项有主外键约束,这是一对多的关系,即一个问题可以有多个选项。每个问题的实例都有一个xxx_set管理器。问题的选项是Choice,那么管理器就是choice_set,如果选项的类名是XuanXiang,那么管理器的名称是xuanxiang_set。
>>> c3 = q1.choice_set.create(choice_text='阿里巴巴')
删除选项
>>> c3.delete()
修改问题
>>> q2.question_text = '从学校毕业后,你打算去哪个城市工作?'
>>> q2.save()
查询所有问题
>>> Question.objects.all()
, , , ]>
#########################################################################
Question.objects.all() //查询所有问题
>>> for q in Question.objects.all():
... print(q.pub_date)
...
2019-05-25 17:29:00
2019-06-07 12:00:00
2019-05-27 09:00:00
2019-06-01 12:00:00
>>> Question.objects.order_by('pub_date')
>>> for q in Question.objects.order_by('pub_date'): //根据发布时间升序排列
... print(q.pub_date)
...
2019-05-25 17:29:00
2019-05-27 09:00:00
2019-06-01 12:00:00
2019-06-07 12:00:00
>>> for q in Question.objects.order_by('pub_date'):
... print(q.pub_date, q.question_text)
...
2019-05-25 17:29:00 从大学毕业后,你期望的新水是多少?
2019-05-27 09:00:00 你期待哪家公司给你发offer?
2019-06-01 12:00:00 从学校毕业后,你打算去哪个城市工作?
2019-06-07 12:00:00 放假后打算去哪里玩?
>>> for q in Question.objects.order_by('-pub_date'): //根据发布时间降序排列
... print(q.pub_date, q.question_text)
...
2019-06-07 12:00:00 放假后打算去哪里玩?
2019-06-01 12:00:00 从学校毕业后,你打算去哪个城市工作?
2019-05-27 09:00:00 你期待哪家公司给你发offer?
2019-05-25 17:29:00 从大学毕业后,你期望的新水是多少?
获取某一个问题的实例
get必须得到一个实例,否则报错
>>> Question.objects.get(id=1) //返回1号问题
>>> Question.objects.get(id=10) //如果不存在,则报错
>>> Question.objects.get(id__gt=1) //id>1的问题,不止一项,报错
获取多个实例
filter可以得到0到多个实例的集合
>>> Question.objects.filter(id=1) //具有一项的查询集
]>
>>> Question.objects.filter(id=10) //查询集为空
>>> Question.objects.filter(id__gt=1) //查询集有多项
, , ]>
查询条件
查询条件采用的形式是“属性__操作符=值”,id=1实际上是id_exact=1的简写
>>> Question.objects.filter(id__exact=1) //等于1
>>> Question.objects.filter(id__gt=1) //大于1
>>> Question.objects.filter(id__gte=1) //大于等于1
>>> Question.objects.filter(id__lt=1) //小于1
>>> Question.objects.filter(id__lte=1) //小于等于1
其他属性与数值属性类似,也是使用__
>>> Question.objects.filter(question_text__startswith='从学校')
]>
>>> Question.objects.filter(pub_date__month=5)
, ]>
视图基础
• 在Django中,网页的页面和其他内容都是由视图来传递的(视图对WEB请求进行回应)
• 每个视图都是由一个简单的Python函数(或者是基于类的视图的方法)表示的
• Django通过检查请求的URL(准确地说,是URL里域名之后的那部分)来选择使用哪个视图
编写URLCONF
• 将视图和polls.urls模块关联
• 当客户端向你的网站请求一个页面 ( 例如“/polls/34/”)时,Django将加载mysite.urls
Python模块
• 因为它被指向ROOT_URLCONF设置, 它寻找名为urlpatterns 的变量并按顺序匹配其中的正则表达式
•在‘^polls/’找到匹配后,它将取消匹配的文本(“polls/”),并发送剩余的文本 ( “34/” )
到’polls.urls’URLconf进行进一步处理
模板概述
• 前面的例子,HTML是硬编码在python代码中的。这会带来不少问题:
– 任何页面的改动会牵扯到Python代码的改动
– 写后台Python代码与设计HTML是不同的工作,更专业的Web开发应该将两者分开
– 程序员写Python代码同时页面设计者写HTML模板会更高效,而不是一个人等待另一个人编辑同样的文件
• 为了解决硬码的这些问题,可以模板:
– 网站的设计改动会比Python代码改动更频繁,所以如果我们将两者分离开会更方便
– 页面设计者和HTML/CSS程序员不应该编辑Python代码,他们应该与HTML打交道
– 使用Django的模板系统分离设计和Python代码会更干净更易维护
创建模板工作目录
• 默认的设置文件settings.py配置了一个DjangoTemplates后端,其中将APP_DIRS选项设置为True
• DjangoTemplates在 INSTALLED_APPS所包含的每个应用的目录下查找名为"templates"子目录
• 模板应该位于polls/templates/polls/目录下
• 当模板系统遇到变量名里有小数点时会按以下顺序查找:
– 字典查找,如foo[“bar”]
– 属性查找,如foo.bar
– 方法调用,如foo.bar()
– 列表的索引查找,如foo[bar]
• 模板中可以使用的元素有:
– 变量,使用 {{ variable }} 的格式
– 标签/指令,使用 {% … %}的格式
– 字符串:{ } 之外的任何东西,都当做字符串处理
表单说明
• 在detail网页模板中,我们为Question对应的每个Choice都添加了一个单选按钮用于选择。 每个单选按钮的value属性是对应的各个Choice的ID。
• 每个单选按钮的name是“choice”。 这意味着,当选择一个单选按钮并提交表单提交时,它将发送一个POST数据choice=#,其中#为选择的Choice的ID
• 由于我们创建一个POST表单(它具有修改数据的作用),所以我们需要小心跨站点请求伪造
• Django已经拥有一个用来防御它的非常容易使用的系统
•简而言之,所有针对内部URL的POST表单都应该使用{% csrf_token %}模板标签
投票视图说明
• request.POST 是一个类似字典的对象,可以通过关键字的名字获取提交的数据
• request.POST[‘choice’] 以字符串形式返回选择的Choice的ID。request.POST 的值永远是字符串
• 如果在POST数据中没有提供request.POST[‘choice’],choice将引发一个KeyError
##################################################################
完善投票首页
修改视图函数,取出所有问题
pycharm设置:右击外层mysite—>Mark Directory as—>Sources Root
# polls/views.py
from django.shortcuts import render
from polls.models import Question //导入模块
# Create your views here.
def index(request):
questions = Question.objects.order_by('-pub_date')
return render(request, 'index.html', {'questions': questions}) //修改首页返回内容
def detail(request, question_id):
return render(request, 'detail.html', {'qid': question_id})
def result(request, question_id):
return render(request, 'result.html', {'qid': question_id})
修改首页模板,显示所有问题
# templates/index.html
投票首页
投票首页
{% for question in questions %}
-
{{ question.question_text }}
{{ question.pub_date }}
{% endfor %}
说明:{{var}}表示变量,{% %}是模板语法标签,在{}以外的是html语法。
为首页中的超链接加上具体的url
# templates/index.html
首页
投票首页
{% for question in questions %}
-
{{ question.question_text }} //添加url
{{ question.pub_date }}
{% endfor %}
修改首页中超链接的url
# templates/index.html
首页
投票首页
{% for question in questions %}
-
{{ question.question_text }}
{{ question.pub_date }}
{% endfor %}
将网页制作用到的static目录拷贝到polls目录下
[root@room8pc16 mysite]# cp -r …/…/day16/static/ polls/
修改index.html首页,使用boostrap
# templates/index.html
{% load static %}
首页
//适应屏幕
//调用css
投票首页
{% for question in questions %}
-
{{ question.question_text }}
{{ question.pub_date }}
{% endfor %}
//以上为轮播图部分
拷贝index.html为base.html
cp index.html base.html
将base.html中的个性内容用block替代
# templates/base.html //base.html保存共性内容
{% load static %}
{% block title %}{% endblock %}
{% block content %}{% endblock %} //index.html中个性内容用block代替
将index.html中的共性删除,将个性内容写到block中
# templates/index.html //index.html中保存个性内容
{% extends 'base.html' %} //扩展连接base.html中共性内容
{% load static %}
{% block title %}投票首页{% endblock %}
{% block content %}
投票首页
{% for question in questions %}
-
{{ question.question_text }}
{{ question.pub_date }}
{% endfor %}
{% endblock %}
修改投票详情页函数
# polls/views.py
from django.shortcuts import render
from polls.models import Question
# Create your views here.
def index(request):
questions = Question.objects.order_by('-pub_date')
return render(request, 'index.html', {'questions': questions})
def detail(request, question_id): //修改投票详情页函数
question = Question.objects.get(id=question_id)
return render(request, 'detail.html', {'question': question})
def result(request, question_id):
return render(request, 'result.html', {'qid': question_id})
修改投票详情页模板文件
# templates/detail.html
{% extends 'base.html' %}
{% load static %}
{% block title %}投票详情{% endblock %}
{% block content %}
{{ question.id }}号问题投票详情
{{ question.question_text }}
{% endblock %}
为投票函数定义URL
# polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
#url(正则,函数,name=该url的名字)
url(r'^$', views.index, name='index'),
url(r'^(?P\d+)/$', views.detail, name='detail'),
url(r'^(?P\d+)/result/$', views.result, name='result'),
url(r'^(?P\d+)/vote/$', views.vote, name='vote'), //投票函数url
]
定义投票函数
# polls/views.py
from django.shortcuts import render
from polls.models import Question
from django.shortcuts import render, redirect
# Create your views here.
def index(request):
questions = Question.objects.order_by('-pub_date')
return render(request, 'index.html', {'questions': questions})
def detail(request, question_id):
question = Question.objects.get(id=question_id)
return render(request, 'detail.html', {'question': question})
def vote(request, question_id): //定义投票函数
# 取出问题
question = Question.objects.get(id=question_id)
if request.method == 'POST':
# 取出用户的选择
choice_id = request.POST.get('choice_id')
# 取出选项实例
choice = question.choice_set.get(id=choice_id)
choice.votes += 1
choice.save()
# redirect相当于打开一个新窗口,访问网址。
# 如果仍然采用render,将会把request的数据继续向result传递
return redirect('result', question_id=question_id)
def result(request, question_id):
return render(request, 'result.html', {'qid': question_id})
修改投票详情页表单的action行为
{% extends 'base.html' %}
{% load static %}
{% block title %}投票详情{% endblock %}
{% block content %}
{{ question.id }}号问题投票详情
{{ question.question_text }}
{% endblock %}
##################################################################
pycharm中项目mysite虚拟环境的目录结构
##################################################################
模拟客户端投票(从大学毕业后,你期望的新水是多少?选择10000+两次)
查看后端投票结果
实现投票结果页
修改函数
from django.shortcuts import render
from polls.models import Question
from django.shortcuts import render, redirect
# Create your views here.
def index(request):
questions = Question.objects.order_by('-pub_date')
return render(request, 'index.html', {'questions': questions})
def detail(request, question_id):
question = Question.objects.get(id=question_id)
return render(request, 'detail.html', {'question': question})
def vote(request, question_id):
# 取出问题
question = Question.objects.get(id=question_id)
if request.method == 'POST':
# 取出用户的选择
choice_id = request.POST.get('choice_id')
# 取出选项实例
choice = question.choice_set.get(id=choice_id)
choice.votes += 1
choice.save()
# redirect相当于打开一个新窗口,访问网址。
# 如果仍然采用render,将会把request的数据继续向result传递
return redirect('result', question_id=question_id)
def result(request, question_id): //修改投票结果页函数
question = Question.objects.get(id=question_id)
return render(request, 'result.html', {'question': question})
修改投票结果页模板
# templates/result.html
{% extends 'base.html' %}
{% load static %}
{% block title %}投票结果{% endblock %}
{% block content %}
{{ question.id }}号问题投票结果
{{ question.question_text }}
选项
票数
{% for choice in question.choice_set.all %}
{{ choice.choice_text }}
{{ choice.votes }}
{% endfor %}
{% endblock %}