Django 开发
一:基础
1.创建项目目录:
django-admin startproject bysms
bysms/ --- 项目根目录
manage.py --工具脚本,用于管理项目
bysms/ --python包,名称创建后不可更改,manege.py 会用到
__init__.py --包
settings.py ---项目配置文件
urls.py -- 总路由,转发请求
wsgi.py --web服务网关接口,由wsgi web server 和wsgi web application 组成,web server(提供高效的http请求处理环境,多线程,多进程、协程的机制) 接受前端的请求后会调用wsgi web application(业务逻辑控制)
2.运行Django web服务
在项目根目录:python manage.py runserver 0.0.0.0:80 --启动服务,即可用浏览器访问127.0.0.1 即可访问web 服务
--0.0.0.0:80 web 服务绑定的ip 和端口,绑定本机所有的地址
3.创建项目app
python manage.py startapp sales
创建一个目录名为 sales, 对应 一个名为 sales 的app,里面包含了如下自动生成的文件
sales/
__init__.py
admin.py apps.py
migrations/
__init__.py
models.py
tests.py
views.py --- 处理http 请求的代码
4.创建子路由
主路由中import include
增加一条路由,通过include 转发到子路由,需要在app中创建 urls.py 文件
from django.contrib import admin
from django.urls import path,include
from sales.views import listorders
urlpatterns = [
path('admin/', admin.site.urls),
# 添加如下的路由记录
path('sales/', include('sales.urls')),
]
app中的urls.py
import处理路由逻辑的类 views.py
增加一条路由,有没有斜线要看具体的接口文档,与主路由拼接成完整的路由,调用views 中的函数来处理不同的请求
from django.urls import path
from . import views
urlpatterns = [
# 添加如下的路由记录
path('orders/', views.listorders),
]
5.创建数据库和表
项目中数据库的配置在 mybysms/settings.py,默认的数据库sqlite3
python manage.py migrate -- 在根目录下生成 db.sqlite3 的数据库
创建 Djiango 必须的基本表
mysql
启动mysql 服务
netstart mysql
终止服务
netstop mysql
连接数据库服务器
mysql -uroot -phuawei@1234
创建数据库
create database Gp1Day15 charset=utf8;
安装驱动
import pymysql
pymysql.install_as_MySQLdb()
执行数据迁移
python manage.py migrate
auth_group : id name
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permissions
django_admin_log
django_content_type
django_migrations
django_session
6.什么是ORM
通常,在Django中
-
定义一张数据库的表 就是定义一个继承自 django.db.models.Model 的类
-
定义该表中的字段(列), 就是定义该类里面的一些属性
-
类的方法就是对该表中数据的处理方法,包括 数据的增删改查
这样,开发者对数据库的访问,从原来的使用底层的 sql 语句,变成 面向对象的开发,通过一系列对象的类定义 和方法调用就可以 操作数据库。
这种 通过 对象 操作数据库 的方法 被称之为 ORM (object relational mapping),下面我们就来看怎样使用。
7.定义数据库表
python manage.py startapp common
打开 common/models.py,导入 models ,继承models.Model,实际生成的表名为app名.类名(小写):common_custormer models.CharField 创建字符型( varchar)的属性
from django.db import models
class Customer(models.Model):
# 客户名称
name = models.CharField(max_length=200)
# 联系电话
phonenumber = models.CharField(max_length=200)
# 地址
address = models.CharField(max_length=200)
在models.py 中创建好表的属性,在settiing 文件中 install_apps 中加入 ‘common.apps.CommonConfig’
告诉Django CommonConfig 是common/apps.py文件中定义的一个应用配置的类。
python manage.py makemigrations common ---告诉Django common app 的models.py 已经被修改了,生成数据库操作代码0001_initial.py 文件
python manage.py migrate -- 执行0001_initial.py 代码,操作数据库,创建表
二:Django Admin管理数据
Django 提供了一个管理员界面可以方便操作数据库
1.创建超级管理员
python manage.py createsupperuser
2.在common/Admin.py 中添加 注册我们定义的model类
from django.contrib import admin
from .models import Customer
admin.site.register(Customer)
管理视图:
三:读取数据库
1.在sales 中导入customer,定义一个listcustomers 函数, data=Customer.objects.values() 返回一个 QuerySet 对象 ,包含所有的表记录,对data 进行遍历,拼接成需要返回的字符串格式,调用HttpResponse(restr)
def listcustomers(request):
# 返回一个 QuerySet 对象 ,包含所有的表记录
# 每条表记录都是是一个dict对象,
# key 是字段名,value 是 字段值
qs = Customer.objects.values()
# 定义返回字符串
retStr = ''
for customer in qs:
for name,value in customer.items():
retStr += f'{name} : {value} | '
# <br> 表示换行
retStr += '<br>'
return HttpResponse(retStr)
2.条件过滤,当用户在浏览器输入 /sales/customers/?phonenumber=13000000001
request.GTE-->字典对象
对customer 表中的数据进行过滤,使用filter
def listcustomers(request):
# 返回一个 QuerySet 对象 ,包含所有的表记录
qs = Customer.objects.values()
# 检查url中是否有参数phonenumber
ph = request.GET.get('phonenumber',None)
# 如果有,添加过滤条件
if ph:
qs = qs.filter(phonenumber=ph)
# 定义返回字符串
retStr = ''
for customer in qs:
for name,value in customer.items():
retStr += f'{name} : {value} | '
# <br> 表示换行
retStr += '<br>'
return HttpResponse(retStr)
filter 的过滤条件可以有多个
qs = qs.filter(phonenumber=ph,address='安徽芜湖')
四:对资源进行增删改查处理
1.Django 的 url路由功能 不支持 根据 HTTP 请求的方法 和请求体里面的参数 进行路由,
自己编写一个函数, 来 根据 http请求的类型 和请求体里面的参数 分发(或者说路由)给 不同的函数进行处理。
def dispatcher(request):
# 将请求参数统一放入request 的 params 属性中,方便后续处理
# GET请求 参数在url中,同过request 对象的 GET属性获取
if request.method == 'GET':
request.params = request.GET
# POST/PUT/DELETE 请求 参数 从 request 对象的 body 属性中获取
elif request.method in ['POST','PUT','DELETE']:
# 根据接口,POST/PUT/DELETE 请求的消息体都是 json格式
request.params = json.loads(request.body)
# 根据不同的action分派给不同的函数进行处理
action = request.params['action']
if action == 'list_customer':
return listcustomers(request)
elif action == 'add_customer':
return addcustomer(request)
elif action == 'modify_customer':
return modifycustomer(request)
elif action == 'del_customer':
return deletecustomer(request)
else:
return JsonResponse({'ret': 1, 'msg': '不支持该类型http请求'})
2.测试后端代码
import requests,pprint
pprint.pprint(response.json())
五:登录
1.session和token
session:
用户登录成功后, 服务端就在数据库session表中 中创建一条记录,记录这次会话
服务端将 用户的信息数据 + 密钥 一起进行一个哈希计算, 得到一个哈希值
request.session['usertype'] = 'mgr'
将用户的类型保存在session 数据中
Django 框架会自动在HTTP响应头中加入类似下面的sessionid cookie
然后在该登录请求的HTTP响应消息中, 的头字段 Set-Cookie 里填入 sessionid 数据。
Set-Cookie: sessionid=???????? 后面的请求会带上这个 sessionid
判断是否登录
if 'usertype' not in request.session
判断是否为管理员
request.session['usertype'] != 'mgr'
session 机制性能问题
验证请求是根据sessionid 到数据库中查找session表的,而数据库操作是服务端常见的性能瓶颈,尤其是当用户量比较大的时候
session 机制扩展性问题
当系统用户特别多的时候,后端处理请求的服务端通常由多个,部署在多个节点上。 但是多个节点都要访问session表,这样就要求数据库服务能够被多个节点访问,不方便切分数据库以提高性能
2.Token 机制
就是包含了 数据信息 和 校验信息的 数据包。
token机制 数据信息 直接传给 客户端,客户每次请求再携带过来给服务端。服务端无需查找数据库,直接根据token里面的数据信息进行校验
服务端配置一个密钥(secret key),该密钥是服务端私密保存的,不能外泄
在用户登录成功后, 服务端将 用户的信息数据 + 密钥 一起进行一个哈希计算, 得到一个哈希值
大家可以发现 token 里面 包含了用户数据信息 和 用于校验完整性的哈希值。
如果客户修改了数据信息, 因为他不知道密钥,没法得到正确的新的哈希值,那么 服务端根据 篡改后的数据+密钥 得到的新 哈希值一定和 保存在token中的老哈希值 不同。
六:数据库
mysql、oracle、 sqlserver、SQLite 都是关系型数据库,而 mongodb、Cassandra不是
常见的3种关联关系就是: 一对多 , 一对一 , 多对多
1.一对多:
jango中定义外键 的方法就是 Model类的该属性字段 值为 ForeignKey 对象
表之间 一对多 的关系,就是 外键 关联关系
class Order(models.Model):
# 订单名
name = models.CharField(max_length=200,null=True,blank=True)
# 创建日期
create_date = models.DateTimeField(default=datetime.datetime.now)
# 客户
customer = models.ForeignKey(Customer,on_delete=models.PROTECT)
on_delete :
1) CASCADE: 删除主键记录和 相应的外键表记录。
2) PROTECT: 禁止删除记录。
3) SET_NULL: 删除主键记录,并且将外键记录中外键字段的值置为null。 当然前提是外键字段要设置为值允许是null
2.一对一
Django 中 用 OneToOneField 对象 实现 一对一 的关系,如下
Django发现这样一对一定定义,它会在migrate的时候,在数据库中定义该字段为外键的同时, 加上unique=True 约束,
表示在此表中,所有记录的该字段 取值必须唯一,不能重复
class Student(models.Model):
# 姓名
name = models.CharField(max_length=200)
# 班级
classname = models.CharField(max_length=200)
# 描述
desc = models.CharField(max_length=200)
class ContactAddress(models.Model):
# 一对一 对应学生
student = models.OneToOneField(Student, on_delete=models.PROTECT)
# 家庭
homeaddress = models.CharField(max_length=200)
# 电话号码
phone = models.CharField(max_length=200)
3.多对多
Django是通过 ManyToManyField 对象 表示 多对多的关系的。
# 订单购买的药品,和Medicine表是多对多 的关系
medicines = models.ManyToManyField(Medicine, through='OrderMedicine')
案例:
创建两张表,学生表中存在一对多的外键
Django shell
python manage.py shell 进入shell 环境
输入数据,创建数据
通过对象访问外键表
s1 = Student.objects.get(name='白月')
s1.country.name
根据外键表
查找Student表中所有 一年级中国 学生
Student.objects.filter(grade=1,country__name='中国').values()
Student.objects.filter(grade=1,country__name='中国')\ .values('name','country__name')
country__name为双下划线
使用 annotate 方法将获取的字段值进行重命名
反向访问
通过 表Model名转化为小写 ,后面加上一个 _set 来获取所有的反向外键关联对象
cn = Country.objects.get(name='中国')
cn.student_set.all()
Django还给出了一个方法,可以更直观的反映 关联关系, 在定义Model的时候,外键字段使用 related_name 参数
cn = Country.objects.get(name='中国')
cn.students.all()
反向过滤:
使用了反向关联名字
Country.objects.filter(students__grade=1).values()
没有指定方向关联名, 则应该使用 表名转化为小写
Country.objects.filter(student__grade=1).values() .distinct()
使用 Django 的 with transaction.atomic(),将一批数据库操作放在事务中,任何一次数据库操作失败了,数据库系统会让整个事务回滚
七: 分页 和 过滤
1.分页
前端发送的请求中需要携带 两个信息: 每页包含多少条记录 和 需要获取第几页
我们定义列出数据请求中 添加 2个url 参数: pagesize 和 pagenum 分别对应这两个信息
创建了 分页对象,在初始化参数里面设定每页多少条记录
pgnt = Paginator(qs, pagesize) 返回的 分页对象 赋值给变量 pgnt。
一页的数据 就可以通过 pgnt.page(pagenum) 获取
总共有多少页,通过 pgnt.count 得到。
2.过滤
”且“
qs.filter(name__contains='乳酸')
qs.filter(name__contains='乳酸').filter(name__contains='注射液')
qs.filter( Q(name__contains='乳酸') & Q(name__contains='注射液'))
--> WHERE name LIKE '%乳酸%' AND name LIKE '%注射液%'
“或”
from django.db.models import Q
qs.filter(Q(name__contains='乳酸'))
qs.filter( Q(name__contains='乳酸') | Q(name__contains='注射液'))
--> WHERE name LIKE '%乳酸%' OR name LIKE '%注射液%'
生产环境框架
修改 ./bysms/settings.py
生产环境,我们使用 Gunicorn 作为 Django的WSGI前端,首先我们需要创建一个 Gunicorn启动配置文件 ./bysms/gunicorn_conf.py
启动Django 后端服务器
八:安装、配置 Nginx
大家首先以root 用户 登录 CentOS 主机,按照下面的步骤安装Nginx
-
先执行命令 yum install gcc 确保gcc编译器安装好
-
先 安装Nginx依赖包 ,执行命令 yum -y install pcre-devel openssl openssl-devel
-
下载、编译、安装 Nginx
执行命令 tar zxvf nginx-1.15.5.tar.gz 解压 代码包
执行命令 cd nginx-1.15.5 进入到代码目录
执行命令 ./configure --prefix=/usr/local/nginx --with-http_ssl_module 配置编译安装选项
执行命令 make && make install 编译安装
Nginx的配置文件路径是:/usr/local/nginx/conf/nginx.conf
启动 Nginx
启动Nginx,必须以root用户执行。
执行命令 /usr/local/nginx/sbin/nginx ,即可启动Nginx服务。
如果启动报错,你需要查看日志文件,可以打开 /usr/local/nginx/logs/error.log 查看错误日志文件。
如果你修改了配置文件,需要重启Nginx,可以执行如下命令
/usr/local/nginx/sbin/nginx -s reload
如果需要关闭Nginx服务,可以执行如下命令
/usr/local/nginx/sbin/nginx -s stop
CREATE USER 'byhy'@'localhost' IDENTIFIED BY 'Mima123$';
GRANT ALL ON *.* TO 'byhy'@'localhost';
予byhy 用户所有权限,就是可以 该DBMS系统上 访问所有数据库里面所有的表
九:Linux 上安装 Redis
安装redis
tar xzf redis-5.0.6.tar.gz
cd redis-5.0.6
make
make test
make install
接下来执行配置 和 启动 Redis 服务的命令
cd utils/ ; ./install_server.sh
Redis 服务就会启动监听在默认端口6379上
和 MySQL 一样,Redis 里面也包含了多个数据库,以数字进行编号,缺省连接是编号为 0 的数据库。
可以使用命令 select 来选择使用哪个Redis数据库,
比如下面的命令就选择编号为1的数据库
> select 1
OK
127.0.0.1:6379[1]>
比如,要为id 为2000 的用户存入等级值 33
127.0.0.1:6379> set user:2000 33
要从Redis获取key为 user:2000 的值
127.0.0.1:6379> get user:2000
查询以 med 开头的key, 使用通配符 *
keys med*
如果要删除一个key和其对应的对象
del user:2001
存入Hashes,就使用客户端命令 hmset 或者 hset ,
hmset 是存入多个字段值
hmset user:2001 level 10 coin 1977 name 白月黑羽
只要存入(或者修改)一个字段值,就用可以使用hset, 比如要修改 coin的值为 2000,
hset user:2001 coin 2000
> hget user:2001 coin
"2000"
就是把 整个用户表 都直接放入 一个hash 里面
可以给这个hash对应的对象 起一个key名为 usertable 。
> hmset usertable u2001 id:2001|level:10|coin:1977|name:白月黑羽1 > hmset usertable u2002 id:2002|level:13|coin:1927|name:白月黑羽2
> hget usertable u2002 "id:2002|level:13|coin:1927|name:\xe7\x99\xbd\xe6\x9c\x88\xe9\xbb\x91\xe7\xbe\xbd2"
Django项目缓存配置
pip install django-redis
然后在 Django 的项目配置文件 settings.py 中,添加如下的缓存配置项
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}应该符合如下两条规则:
-
频繁读取的数据
否则使用缓存,性能提升也不大
-
较少变动的数据