怎样制作微信网站,有哪些公司网站建设比较好,廊坊网站定制开发,图片制作教程一.前言
上一节简单的讲了一下orm#xff0c;主要还是做个了解#xff0c;这一节将和大家介绍更加细致的orm#xff0c;以及他们的用法#xff0c;到最后再和大家说一下cookie和session#xff0c;就结束了全部的django基础部分
二.orm的基本操作
1.settings.py#x…一.前言
上一节简单的讲了一下orm主要还是做个了解这一节将和大家介绍更加细致的orm以及他们的用法到最后再和大家说一下cookie和session就结束了全部的django基础部分
二.orm的基本操作
1.settings.py连接数据库 2.settings.py注册app 3.各app下面的models.py 编写models.类 class UserInfo(models.Model): ..... ..... 4.执行命令 python manage.py makemigrations # 找到所有已注册的app中的models.py中的类读取 - migrations配置 python manage.py migrate # 读取已注册的app下的migrations配置 - SQL语句 - 同步数据库 三.连接数据库
我们django支持各种类型的数据库例如mysqlsqlite3默认的等等我们连接不同的数据库需要的是改settings.py下面的DATABASES
1.连接django默认自带的sqlite3 DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / db.sqlite3, } } 2.连接mysql 安装MySQL 启动MySQL服务 手动创建数据库 django的settings.py配置 DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: xxxxxxxx, # 数据库名字 USER: root, PASSWORD: root123, #数据库密码 HOST: 127.0.0.1, # ip PORT: 3306, } } 安装第三方组件两个选一个推荐安装pymysql pymysql pip install pymysql 项目根目录/项目名目录/__init__.pyimport pymysqlpymysql.install_as_MySQLdb() mysqlclient pip install mysqlclient 电脑上先提前安装MySQL。 四.连接池
django默认内置没有数据库连接池 所以我们要使用第三方的。 pip install django-db-connection-pool DATABASES { default: { ENGINE: dj_db_conn_pool.backends.mysql, NAME: day04, # 数据库名字 USER: root, PASSWORD: root123, HOST: 127.0.0.1, # ip PORT: 3306, POOL_OPTIONS: { POOL_SIZE: 10, # 最小 MAX_OVERFLOW: 10, # 在最小的基础上还可以增加10个即最大20个。 RECYCLE: 24 * 60 * 60, # 连接可以被重复用多久超过会重新创建-1表示永久。 TIMEOUT:30, # 池中没有连接最多等待的时间。 } } } 五.多数据库
多数据库我们平时都用不上只有在后续开发大项目时才能用得上大家做个了解就好 DATABASES { default: { ENGINE: dj_db_conn_pool.backends.mysql, NAME: day05db, # 数据库名字 USER: root, PASSWORD: root123, HOST: 127.0.0.1, # ip PORT: 3306, POOL_OPTIONS: { POOL_SIZE: 10, # 最小 MAX_OVERFLOW: 10, # 在最小的基础上还可以增加10个即最大20个。 RECYCLE: 24 * 60 * 60, # 连接可以被重复用多久超过会重新创建-1表示永久。 TIMEOUT: 30, # 池中没有连接最多等待的时间。 } }, bak: { ENGINE: dj_db_conn_pool.backends.mysql, NAME: day05bak, # 数据库名字 USER: root, PASSWORD: root123, HOST: 127.0.0.1, # ip PORT: 3306, POOL_OPTIONS: { POOL_SIZE: 10, # 最小 MAX_OVERFLOW: 10, # 在最小的基础上还可以增加10个即最大20个。 RECYCLE: 24 * 60 * 60, # 连接可以被重复用多久超过会重新创建-1表示永久。 TIMEOUT: 30, # 池中没有连接最多等待的时间。 } }, } 5.1 读写分离
我们有时候会进行读写分离这个就需要用到多数据库我们配置如下 192.168.1.2 default master [写] 组件 192.168.2.12 bak slave [读] 生成数据库表 python manage.py makemigrations # 找到所有已注册的app中的models.py中的类读取 - migrations配置 python manage.py migrate python manage.py migrate --databasedefault python manage.py migrate --databasebak 后续再进行开发时 models.UserInfo.objects.using(default).create(title外交部) models.UserInfo.objects.using(bak).all() 我们通过using来选择配置的数据库 我们这里看不见数据是因为读取的数据库我们没有做同步的组件
我们发现我们这样读写分离时每次都要选择指定的数据库这样很难整我们可以手动编写router类让我们每次不需要指定就能知道
编写router类两个函数必须叫这个名字 class DemoRouter(object):def db_for_read(self,model,**hints):return settings下面DATABASES的键def db_for_write(self,model,**hints):return settings下面DATABASES的键 然后我们在settings里面配置一下 DATABASE_ROUTERS[utils.router.DemoRouter]这样就是基本的router然后我们还可以进行更细致的判断 我们说两个常用的对象 model._meta.app_label #app的名字
model._meta.model_name #modelss的名字全小写也就是表名我们也可以基于这个来判断用哪个表
5.2 分库多app
也叫多app对应多个数据库 如图我们两个app里有两个model我们想吧一个app的放在default数据库另一个app的放在bak数据库这个时候我们提交的命令就要改然后就借助我们前面说的router进行判断以此来选择数据库 python manage.py makemigrations python manage.py migrate 第一个app名字 --databasedefault python manage.py migrate 第二个app名字 --databasebak ....... 提交好后我们就来开始编辑router 我们现在就通过了一个简单的if判断实现了不同app选择不同数据库的需求了 5.3 分库单app
在一个app中我们想把多个模型拆分到不同的数据库中就需要但是此时我们使用命令是无法完成的我们就需要借助router来编写了 例如这个我们想把第一张表放在default里面下面两张表放在bak里面 def allow_migrate(self,db,app_label,model_nameNone,**hints):执行这个命令的时候python manage.py migrate app名字 --databasedefaultapp_labelapp名字dbdefaultmodel_name 就是models里面的名字全小写通过return True 和False判断是否生成pass 我们同样还是先执行python manage.py makemigrations 我们编写好后执行
python manage.py migrate web --databasedefault
migrate web --databasebak
注意当我们--databasebak 一定要加上app名字 不然会不成功
六.表关系
这个我们在上一节已经给大家介绍过了具体的比如参数我就不介绍这里就直接放代码
一对多
from django.db import modelsclass Depart(models.Model):titlemodels.CharField(verbose_name标题,max_length32,uniqueTrue)class UserInfo(models.Model):namemodels.CharField(verbose_name姓名,max_length32,db_indexTrue)dpmodels.ForeignKey(toDepart,on_deletemodels.CASCADE)class Meta:db_tabledepart
这个最后的class Meta下面的db_tabledepart的意思是让在数据库创建的表名为depart入过不设置的话就是app名字_类名的小写我们一般都不会设置因为这样可以避免表名冲突这里也是给大家引个介绍
多对多
from django.db import models
class Boy(models.Model):name models.CharField(verbose_name姓名, max_length32)class Girl(models.Model):name models.CharField(verbose_name姓名, max_length32)class B2G(models.Model):bidmodels.ForeignKey(toBoy,on_deletemodels.CASCADE)gidmodels.ForeignKey(toGirl,on_deletemodels.CASCADE)
这里我们就不用ManyToManyField这个字段了上一节也说了 一对一
这个是上一节没和大家介绍的当然肯定有人要问一对一有啥好用的为什么不创建一张表呢但是大家想一想在有的特殊的场景里面就拿CSDN来说我们是不是注册需要名称和密码但是此时此刻我们还没有开通博客专区如果我们要开通博客专区是不是又得创建一张博客表里面存放我们博客的地址和简介页面这个时候就会用到一对一
from django.db import models
class UserInfo(models.Model):namemodels.CharField(verbose_name姓名,max_length32,db_indexTrue)dpmodels.ForeignKey(toDepart,on_deletemodels.CASCADE)class Blog(models.Model):usermodels.OneToOneField(toUserInfo,on_deletemodels.CASCADE)blogmodels.CharField(verbose_name博客地址,max_length128)summerymodels.CharField(verbose_name简介,max_length255)
七.数据操作
7.1 单表数据操作
以这个数据库为例 class Role(models.Model):titlemodels.CharField(verbose_name标题,max_length32)odmodels.IntegerField(verbose_name排序,default0) 1.创建 obj1 models.Role.objects.create(title管理员, od1)
obj2 models.Role.objects.create(**{title: 管理员, od: 1})
#通过以上两种直接创建数据多用下面的那种数据少用上面的那种记住下面的字典前面一定要加上**obj models.Role(title客户, od1)
obj.od 100
obj.save()obj models.Role(**{title: 管理员, od: 1})
obj.od 100
obj.save()
#这种是先创建对象放在内存里面创建完的对象可以修改值然后.save()就可以提交到数据库2.删除
删除很简单理论上就是先查找再删除只要记住找到对象然后再.delete() models.Role.objects.all().delete()
models.Role.objects.filter(title管理员).delete()
#第一个是查找全部的对象第二个filter里面是跟着各种条件找到以后delete()就行了他们的返回值是受影响的行数 3.更新
更新和删除的原理都一样只要记得找到对象然后再update(数据) models.Role.objects.all().update(od99)
models.Role.objects.filter(id7).update(od99, title管理员)
models.Role.objects.filter(id7).update(**{od: 99, title: 管理员})4.查找
我们前面删除和更新其实都用到查询了大家可以发现查询可以查询全部也可以筛选完查询查询得到的结果类型是QuerySet里面套着obj类型很像列表但是不是我们可以for循环得到里面的每个元素并且查询得到得返回值还可以.query得到他原本查询得命令 v1 models.Role.objects.all()
for obj in v1:print(obj, obj.id, obj.title, obj.od)v2 models.Role.objects.filter(**{od: 99, id: 99}) #和前面一样支持两种
for obj in v2:print(obj, obj.id, obj.title, obj.od)v3 models.Role.objects.filter(id99)
print(v3.query)v3 models.Role.objects.filter(id__gt2)
print(v3.query)v3 models.Role.objects.filter(id__gte2)
print(v3.query)v3 models.Role.objects.filter(id__lt2)
print(v3.query)v3 models.Role.objects.filter(id__in[11, 22, 33])
print(v3.query)v3 models.Role.objects.filter(title__contains户)
print(v3.query)v3 models.Role.objects.filter(title__startswith户)
print(v3.query)v3 models.Role.objects.filter(title__isnullTrue)
print(v3.query)# 不等于
v3 models.Role.objects.exclude(id99)
print(v3.query)#不等于完还能再筛选
v3 models.Role.objects.exclude(id99).filter(od88)
print(v3.query) 大家执行一下然后再看query语句就知道了我在这里总结一下
全部用.all()筛选让条件满足用.filter(id99)筛选让条件取反.exclude(id99) __gt 大于 __gte 大于等于 __lt 小于 __lte 小于等于 __in[11, 22, 33] 在这个里面 __contains“户” 包含这个 __startswith户 以户开头 __isnullTrue 为空 我们上面说的都是QuerySet里面套着obj但是接下来会讲一些有用的 v4 models.Role.objects.filter(id__gt0).values(id, title)
print(v4)
v4 models.Role.objects.filter(id__gt0).values_list(id, title)
print(v4)
v4models.Role.objects.all().first()
print(v4)
v4 models.Role.objects.filter(id__gt0).values(id, title).first()
print(v4)
v4 models.Role.objects.filter(id__gt10).exists() #判断这个对象是否存在 返回True或者False
print(v4)
# asc
v8 models.Role.objects.filter(id__gt0).order_by(id)
print(v8)
# id desc od asc
v9 models.Role.objects.filter(id__gt0).order_by(-id, od)
print(v9) 我们所有的都总结一下就是通过.filter()和.all()拿到的数据就是QuerySet[obj,obj,obj]这种类型的数据。
如果我们想要改变里面的数据类型就可以再在后面加上.value()和.values_list()不过这里就要加上子弹名字分别以这些字段构成的字典和元组只要类型是QuerySet我们既可以通过.first()拿到QuerySet的第一个元素无论是对象字典元组。
如果我们想判断QuerySet是否不为空就用.exists()。
如果我们想对拿到的QuerySet里面的元素无论是对象字典元组进行排序就用.order_by()里面的参数就是字段名这就是想升序字段名前面加了个-就是降序如果有多个值就是以第一个值为准如果第一个值一样就按照第二个的来排理解这些是不是对这些参数运用熟悉多了所以学习这些还是得先学会数据类型。
7.2 一对多数据操作 class Depart(models.Model):titlemodels.CharField(verbose_name标题,max_length32,uniqueTrue)class UserInfo(models.Model):namemodels.CharField(verbose_name姓名,max_length32,db_indexTrue)dpmodels.ForeignKey(toDepart,on_deletemodels.CASCADE) 我们一对多以这个数据库为例当然有很多都是和单表操作是重复的我这里只和大家说不是重复的部分也不会和上面讲的那么细
1.创建 models.UserInfo.objects.create(name往日情怀酿作酒,dp_id1)objmodels.Depart.objects.filter(id2).first()
models.UserInfo.objects.create(name往日情怀酿作酒,dpobj)
models.UserInfo.objects.create(name往日情怀酿作酒,dp_idobj.id)这里在我们创建ForeignKey关联字段的时候他在表中的名字会加上_关联字段名字因为我们上面没有指定to_field所以默认指定到了id我们也可以直接用字段但是后面的参数就要是个对象了
2.更新
这里我就给大家介绍一个需要注意的点我们可以通过ForeignKey__标题来实现跨表操作但是我们更新只能本表数据 models.UserInfo.objects.filter(name往日情怀酿作酒).update(dp_id2)#这个是没有问题的
models.UserInfo.objects.filter(id2).update(dp__title销售部)#这样是不行的不能删跨表更改3.查找
这里不和大家说删除了是因为主要就是查找和前面没什么区别介绍创建主要是为了和大家说一下ForeignKey关联的字段 v1models.UserInfo.objects.all()
for obj in v1: #但是如果要跨表也就是加上__字段我们通常不会用这个因为这个效率太差了print(obj.name,obj.id,obj.dp_id) #我们可以通过ForeignKey字段名__另一张表名来跨表v2models.UserInfo.objects.all().select_related(dp)
for obj in v2: #加上.select_related(depart)相当于把两张表给连起来了效率就会高很多print(obj.name,obj.id,obj.dp_id)v3models.UserInfo.objects.all().values(id,name,dp__title)
print(v3)v3 models.UserInfo.objects.all().values_list(id, name, dp__title)
print(v3) 我们可以通过ForeignKey字段__来找到跨表的数据这个是需要关注的
4.重点容易犯毛病 #正向操纵
# 我们可以通过ForeignKey进行跨表这个是没有问题的
v1models.UserInfo.objects.all().values(id,name,dp_id,dp__title)
print(v1)#反向操作
#django里面会默认把我们用ForeignKey关联的表也可以通过__来连接起来
#例如这个关联了userinfo那么userinfo也就是代表这个表关联字段的iduserinfo__name代表跨的表名
v2models.Depart.objects.all().values(id,title,userinfo,userinfo__name)
print(v2) 但是我们假设一下如果用户表里面有两个ForeignKey那么他这个表名到底是关联的哪一个ForeignKey字段的id呢那我们先来更新一下表 我们按照我们需求创建一个新部门new_dp也是ForeignKey关联的但是当我们更新表的时候他会提示报错这是因为django关联表的时候已经想到反向关联表会出现冲突这个时候我们就要加上related_name用来做为反向关联的 class UserInfo(models.Model):namemodels.CharField(verbose_name姓名,max_length32,db_indexTrue)dpmodels.ForeignKey(toDepart,on_deletemodels.CASCADE,related_namedp1)new_dpmodels.ForeignKey(toDepart,on_deletemodels.CASCADE,related_namedp2,default1) related_name就是当多个ForeignKey关联同一个表时要加上的到时候我们反向关联就不能用表名了而是要用related_name 7.3 多对多数据操作 class Boy(models.Model):name models.CharField(verbose_name姓名, max_length32)class Girl(models.Model):name models.CharField(verbose_name姓名, max_length32)class B2G(models.Model):bidmodels.ForeignKey(toBoy,on_deletemodels.CASCADE)gidmodels.ForeignKey(toGirl,on_deletemodels.CASCADE)adressmodels.CharField(verbose_name约会地点,max_length32,default北京中路八号ma)1.创建 models.Boy.objects.create(name宝强)
models.Boy.objects.create(name羽凡)
models.Boy.objects.create(name乃亮)models.Girl.objects.bulk_create(objs[models.Girl(name小路), models.Girl(name百合), models.Girl(name马蓉)],batch_size3
)models.B2G.objects.create(bid_id1, gid_id3, adress北京)
models.B2G.objects.create(bid_id1, gid_id2, adress上海)
models.B2G.objects.create(bid_id2, gid_id2, adress芜湖)
models.B2G.objects.create(bid_id2, gid_id1, adress安庆) 这里都一样但是补前面没说的知识点就是批量创建 用.bulk_create参数是objs[]里面是models.表名不用加上objectsbatch_size就是一次提交几个如果数据多于batch_size那么就第二次创建
2.查找 # 1.宝强都与谁约会。
q models.B2G.objects.filter(bid__name宝强).select_related(gid)
for item in q:print(item.id, item.adress, item.bid.name, item.gid.name)# 2.百合 都与谁约会。
q models.B2G.objects.filter(gid__name百合).values(id, bid__name, gid__name)
for item in q:print(item[id], item[bid__name], item[gid__name]) 这个没啥特殊的就举几个例子和大家看看
7.4 一对一数据操作
一对多大家都会一对一怎么可能会不会呢我就不多写了难打字
八.cookie和session
8.1 cookie
cookie前面都给大家介绍过了这里来说一些用到的重要参数 def show(request):resHttpResponse(返回)res.set_cookie(name,Mr.7,max_age100,path/,domainwww.yy.com,secureFalse,httponlyTrue)return res max_agecookie存活时间 path哪些路径会携带这个cookie domain哪些域名会携带这个cookie secure是否只在https下携带 httponly只允许请求使用cookie这些参数不写也可以 这里要注意一下就是当我们用到域名的时候要在这里加上通常使用*
8.2 session
session我们通常都是和cookie一起这样比较方便 用到session我们的这个中间件一定要打开
文件配置 SESSION_ENGINE django.contrib.sessions.backends.file
SESSION_FILE_PATH session
SESSION_COOKIE_NAME sid # Session的cookie保存在浏览器上时的key即sessionid随机字符串
SESSION_COOKIE_PATH / # Session的cookie保存的路径
SESSION_COOKIE_DOMAIN None # Session的cookie保存的域名
SESSION_COOKIE_SECURE False # 是否Https传输cookie
SESSION_COOKIE_HTTPONLY True # 是否Session的cookie只支持http传输
SESSION_COOKIE_AGE 1209600 # Session的cookie失效日期2周SESSION_EXPIRE_AT_BROWSER_CLOSE False # 是否关闭浏览器使得Session过期
SESSION_SAVE_EVERY_REQUEST True # 是否每次请求都保存Session默认修改之后才保存数据库配置 我们要把这个session的app给打开并且重新执行makemigrations和migrate让他重新生成session的数据库 # session SESSION_ENGINE django.contrib.sessions.backends.db SESSION_COOKIE_NAME sid # Session的cookie保存在浏览器上时的key即sessionid随机字符串 SESSION_COOKIE_PATH / # Session的cookie保存的路径 SESSION_COOKIE_DOMAIN None # Session的cookie保存的域名 SESSION_COOKIE_SECURE False # 是否Https传输cookie SESSION_COOKIE_HTTPONLY True # 是否Session的cookie只支持http传输 SESSION_COOKIE_AGE 1209600 # Session的cookie失效日期2周 SESSION_EXPIRE_AT_BROWSER_CLOSE False # 是否关闭浏览器使得Session过期 SESSION_SAVE_EVERY_REQUEST True # 是否每次请求都保存Session默认修改之后才保存 缓存版
我们首先要创建缓存这里介绍用redis首先要安装模块 pip install django-redis 再在settings.py里面创建 CACHES CACHES { default: { BACKEND: django_redis.cache.RedisCache, LOCATION: redis://127.0.0.1:6379, OPTIONS: { CLIENT_CLASS: django_redis.client.DefaultClient, CONNECTION_POOL_KWARGS: {max_connections: 100} # PASSWORD: 密码, } } } # session SESSION_ENGINE django.contrib.sessions.backends.cache SESSION_CACHE_ALIAS default SESSION_COOKIE_NAME sid # Session的cookie保存在浏览器上时的key即sessionid随机字符串 SESSION_COOKIE_PATH / # Session的cookie保存的路径 SESSION_COOKIE_DOMAIN None # Session的cookie保存的域名 SESSION_COOKIE_SECURE False # 是否Https传输cookie SESSION_COOKIE_HTTPONLY True # 是否Session的cookie只支持http传输 SESSION_COOKIE_AGE 1209600 # Session的cookie失效日期2周 SESSION_EXPIRE_AT_BROWSER_CLOSE False # 是否关闭浏览器使得Session过期 SESSION_SAVE_EVERY_REQUEST True # 是否每次请求都保存Session默认修改之后才保存 九.总结
今天的内容有很多主要就是麻烦大家后期肯定会大量的用到毕竟是最重要的所以内容多也很正常我感觉主要还是得先理解数据类型这样就会更好理解
十.补充
下一期将和大家开始讲项目期待大家的点赞关注加收藏