1、Django数据库
Django 非常适合构建数据库驱动型网站,它提供了简单而强大的工具(ORM),易于使用 Python 执行数据库查询。
2、ORM介绍
Object Relational Mapping,简称ORM(对象关系映射)将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式(对象)转换到另外一种形式(数据库表格)。
3、数据库建模
Django的数据库模型,必须要在App当中的models中创建。
3.1 模型的搭建
例如,以电商的实体关系建模,模型如下:
默认情况下,Django会给每一个模型添加下面字段
id = models.AutoField(primary_key=True)
模型的搭建
from django.db import models
# Create your models here.
class Seller(models.Model):
"""seller卖家"""
name = models.CharField(max_length=64)
password = models.CharField(max_length=64)
nickname = models.CharField(max_length=64, null=True)
gender = models.CharField(max_length=64, null=True)
age = models.IntegerField(null=True)
# ImageField图片路径
picture = models.ImageField(null=True)
phone = models.CharField(max_length=64, null=True)
address = models.CharField(max_length=64, null=True)
# EmailField自带邮箱格式验证
email = models.EmailField(max_length=64, null=True)
createtime = models.DateTimeField(null=True)
def __str__(self):
return self.name
class Meta:
db_table = "seller" # 指定表名
class Store(models.Model):
"""store店铺"""
name = models.CharField(max_length=64)
description = models.TextField(null=True)
address = models.CharField(max_length=64)
picture = models.ImageField(null=True)
seller = models.OneToOneField(to=Seller, on_delete=models.CASCADE) # 一对一关系
goodstypes = models.ManyToManyField(to="GoodsType", db_table="store_goodstype") # db_table指定中间表的名字
def __str__(self):
return self.name
class Meta:
db_table = "store" # 指定表名
class GoodsType(models.Model):
"""store店铺"""
name = models.CharField(max_length=64)
description = models.TextField(null=True)
picture = models.ImageField(null=True)
def __str__(self):
return self.name
class Meta:
db_table = "goodstype" # 指定表名
class Goods(models.Model):
"""store店铺"""
name = models.CharField(max_length=64)
price = models.IntegerField(null=True)
number = models.IntegerField(null=True)
sale = models.IntegerField(null=True)
picture = models.ImageField(null=True)
description = models.TextField(null=True)
detail = models.TextField(null=True)
producttime = models.DateField(null=True)
shelfife = models.IntegerField(null=True)
unite = models.CharField(max_length=64)
# 冗余,方便查询商品与店铺
store_id = models.IntegerField(null=True)
goodstype = models.ForeignKey(to=GoodsType, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Meta:
db_table = "goods" # 指定表名
ImageField字段需要安装pillow包,未安装则会报错
pip install pillow
3.2 常用的字段
字段名称 | 字段描述 |
---|---|
CharField | 字符串类型,必须设置max_length |
IntergerField | 整数类型 |
FloatField | 小数类型 |
EmailField | 邮件格式的字符串 |
TextField | 文本类型 |
DateField | 日期 年月日 |
DateTimeField | 时间 年月日时分秒 |
FileField | 文件类型 特殊类型,可以保存文件路径同时自动上传文件 必须设置upload_to上传到媒体路径下的位置 |
ImageField | 图片文件类型 特殊类型,可以保存文件路径同时自动上传文件,upload_to上传到媒体路径下的位置,需要在settings中配置媒体路径。 |
电话类型 | 必须是美国座机格式的电话号码 |
注:媒体路径的配置
3.3 常用的字段参数
参数名称 | 参数描述 |
---|---|
verbose_name | 别名,在后台可以使用 |
default | 默认值 |
unique | 不可以重复 |
blank | 可以为空,常用于字符串 |
null | 可以为null,常用于数字,和时间 |
max_length | 字符类似的长度 |
upload_to | 文件上传地址 |
Auto_now | 默认当前时间 |
4、数据库配置
4.1 配置sqlite3数据库
Django默认配置的就是sqlite3数据库,配置信息如下:
4.2 配置mysql数据库
4.2.1 编写配置信息
4.2.2 下载pymysql
pip install pymysql
注意:Python2 版本中使用的是MySQLdb的模块,现在用的是Python3版本,由 PyMySQL取代
在项目包下安装pymysql,兼容mysqldb
排错,由于Django2.2.1 和 PyMySQL 不兼容,需要修改源码
进入base.py,注释版本判断
修改版本判断后,因python3中字符串没有decode方法,,operations.py报错,把decode修改为encode
4.3 数据迁移
在Django 的ORM操作当中,数据库操作需要进行命令同步
4.3.1 检查
python manage.py check
4.3.2 生成映射文件
python manage.py makemigrations
4.3.3 迁移到数据库中
python manage.py migrate
5、ORM操作数据库
django可以通过命令开启命令行模式对模型进行操作,命令如下:
python manage.py shell
但默认的命令行并不支持tab补全操作,我们可以安装ipython来实现在命令行模式中使用tab补全操作。
pip install ipython
5.1 增
In [2]: s = Seller()
In [3]: s.name = "laowang"
In [4]: s.password = "123"
In [5]: s.save()
In [8]: Seller.objects.create(
...: name="隔壁",
...: password="123",
...: age=18)
Out[8]: <Seller: Seller object (2)>
5.2 删
In [9]: Seller.objects.get(id=1)
Out[9]: <Seller: Seller object (1)>
In [10]: Seller.objects.get(pk=1)
Out[10]: <Seller: Seller object (1)>
In [11]: s = Seller.objects.get(pk=1)
In [12]: s.delete()
Out[12]: (1, {'store.Seller': 1})
5.3 改
In [14]: s = Seller.objects.get(id=2)
In [15]: s.name = "laowang"
In [16]: s.save() # 数据的更新和保存都是用save,根据id判断,有数据就更新,没有则添加
5.4 查
5.4.1 get
返回与所给筛选条件相匹配的对象。
返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
返回具体的某个模型类的对象,而不是QuerySet列表对象。
In [9]: Seller.objects.get(id=1)
Out[9]: <Seller: Seller object (1)>
In [10]: Seller.objects.get(pk=1)
Out[10]: <Seller: Seller object (1)>
5.4.2 filter
返回包含了与所给筛选条件相匹配的对象,返回 QuerySet 列表对象。获取对象时,通过索引或者遍历可以传入多个关键字,底层的sql 使用and 来连接多个条件
In [2]: Seller.objects.filter(gender="男")
Out[2]: <QuerySet [<Seller: Seller object (2)>,<Seller: Seller object (10)>]>
Seller.objects.filter(gender="男",age__gt=30)
Out[3]: <QuerySet []>
5.4.3 all
获取所有
In [4]: Seller.objects.all()
5.4.4 order_by
排序
In [5]: Seller.objects.order_by("id") # 排序
In [6]: Seller.objects.order_by("-id") # 排倒序
5.4.5 first,last
获取第一个,获取最后一个。
In [7]: Seller.objects.filter(gender="男").first()
Out[7]: <Seller: Seller object (2)>
In [8]: Seller.objects.filter(gender="男").last()
Out[8]: <Seller: Seller object (10)>
5.4.6 双下划线查询
条件 | 描述 | 举例 |
---|---|---|
__gt | 大于 | Seller.objects.filter(id__gt=4) |
__lt | 小于 | Seller.objects.filter(id__lt=2) |
__gte | 大等于 | Seller.objects.filter(id__gte=2) |
__lte | 小等于 | Seller.objects.filter(id__lte=2) |
__contains | 模糊查询 相当于sql like(%keywords%) | Seller.objects.filter(phone__contains=‘153’) |
__in | 判断在范围 | Seller.objects.filter(id__in=[1,2,3]) |
__isnull | 判断为空 | Seller.objects.filter(phone__isnull=False) |
__startswith | 获取以指定内容开头的记录 | Seller.objects.filter(phone__startswith=‘13’) |
5.4.7 聚合查
from django.db.models import Sum,Avg,Max,Min,Count
In [10]: Seller.objects.filter(gender="男").aggregate(Count("id"))
Out[10]: {'id__count': 5}
In [11]: Seller.objects.all().aggregate(Avg("age"))
Out[11]: {'age__avg': 22.6}
5.4.8 分组查
In [12]: Seller.objects.all().values("gender").annotate(Count("id"))
Out[12]: <QuerySet [{'gender': '女', 'id__count': 5}, {'gender': '男', 'id__count': 5}]>
5.4.9 F查询
F()的实例引用一个模型字段。可以比较同一个模型实例中的两个字段。
查询id小于年龄的数据
from django.db.models import F
In [15]: Seller.objects.filter(pk__gt=F("age"))
Out[15]: <QuerySet [<Seller: Seller object (10)>]>
5.4.10 Q查询
filter() 等的关键字参数指定的条件是并联在一起的,如果需要执行更复杂的查询(例如,使用or语句查询),可以使用 Q 对象。
符号 | 描述 |
---|---|
| | 或 |
& | 且 |
~ | 非 |
In [18]: from django.db.models import Q
In [19]: Seller.objects.filter(Q(age__gt=20)|Q(gender="男")) # or
Out[19]: <QuerySet [<Seller: Seller object (1)>, <Seller: Seller object (3)>]>
In [20]: Seller.objects.filter(Q(age__gt=20)&Q(gender="男")) # and
Out[20]: <QuerySet [<Seller: Seller object (2)>]>
In [21]: Seller.objects.filter(~Q(gender="男")) # not
Out[21]: <QuerySet [<Seller: Seller object (1)>, <Seller: Seller object (3)>]>
5.4.11 分页
Django本身有携带分页函数,可以自动分页,但是也有限制查的方法,使用索引,因为Django ORM查询的结果集是一个QueryList(类列表对象),所以可以用索引。
In [22]: Seller.objects.filter(gender="男")[:2]
Out[22]: <QuerySet [<Seller: Seller object (1)>, <Seller: Seller object (3)>]>
6、关系操作
6.1 一对一关系
6.1.1 增
In [6]: s = Seller.objects.create(
...: name="laowang",
...: password="123")
In [7]: store = Store.objects.create(
...: name="老王水饺店",
...: seller=s)
6.1.2 删
In [9]: s.delete()
Out[9]: (2, {'store.Store': 1, 'store.Seller': 1})
6.1.3 改
从外键处添加
In [10]: store = Store.objects.get(id=1)
In [11]: s = Seller.objects.get(id=11)
In [12]: store.seller = s
In [13]: store.save()
6.1.4 查
In [10]: store = Store.objects.get(id=1)
In [11]: s = Seller.objects.get(id=11)
In [16]: s
Out[16]: <Seller: laowang>
In [17]: store
Out[17]: <Store: 星星1号店>
In [18]: store.seller
Out[18]: <Seller: laowang>
In [19]: store.seller_id
Out[19]: 11
In [20]: store.seller.id
Out[20]: 11
6.2 一对多关系
使用Foreign Key,在一方(GoodsType)会自动增加一个属性goods_set,方便一方查询多个数据
foreign key 和manytomany 集合属性,有add新增,remove移除,clear清除,all()查所有返回QuerySet,还有其他的,使用dir查看。
字段参数:
字段参数 | 描述 |
---|---|
to | 设置要关联的表 |
to_field | 设置要关联的表的字段 |
on_delete | 当删除关联表中的数据时,当前表与其关联的行的行为 |
6.2.1 增
给商品类型为3的添加一个商品
In [2]: goodstype = GoodsType.objects.get(id=3)
In [3]: goods = Goods.objects.create(name="辣条",goodstype=goodstype)
In [4]: goods
Out[4]: <Goods: 辣条>
# add添加
In [74]: goodstype = GoodsType.objects.get(id=3)
In [75]: g = Goods.objects.create(name="螺蛳粉")
In [76]: goodstype.goods_set.add(g)
In [77]: goodstype.save()
6.2.2 删
删除商品类型3
In [5]: goodstype = GoodsType.objects.get(id=3)
In [6]: goodstype.delete()
Out[6]: (5, {'store.Store_goodstypes': 0, 'store.Goods': 4, 'store.GoodsType': 1})
6.2.3 改
将id是3的商品的类型改为2类型
goods = Goods.objects.get(id=3)
goodstype = GoodsType.objects.get(id=2)
goods.goodstype = goodstype
goods.save()
5.2.4 查
查询类型2的下的所有商品
In [15]: goodstype = GoodsType.objects.get(id=2)
In [16]: goodstype.goods_set.all()
Out[16]: <QuerySet [<Goods: 燕塘牛奶>, <Goods: 可口可乐>, <Goods: 雪碧>]>
6.3 多对多关系
店铺和商品类型多对多,使用ManyToMany。
任选1方(Store)加ManyToMany,会在另一方(GoodsType)自动增加一个属性store_set,goodstype可以根据这个属性来查询该类型下的所有商品。
In [21]: goodstype = GoodsType.objects.get(id=1)
In [22]: goodstype.store_set.all()
Out[22]: <QuerySet [<Store: 星星1号店>, <Store: 星星2号店>, <Store: 星星4号店>]>
6.3.1 增
新增一个商品类型,增加到店铺1中
In [23]: gt = GoodsType.objects.create(name="药品")
In [24]: gt
Out[24]: <GoodsType: 药品>
In [25]: s = Store.objects.get(id=1)
In [26]: s.goodstypes.add(gt)
In [27]: s.save()
6.3.2 删
删除id为1的店铺
In [29]: s = Store.objects.get(id=1)
In [30]: s.delete()
Out[30]: (3, {'store.Store_goodstypes': 2, 'store.Store': 1})
6.3.3 改
id为2的店铺新增商品类型2,删除商品类型1
In [44]: s = Store.objects.get(id=2)
In [45]: gt1 = GoodsType.objects.get(id=1)
In [46]: gt2 = GoodsType.objects.get(id=2)
In [47]: s.goodstypes.add(gt2)
In [48]: s.goodstypes.remove(gt1)
In [49]: s.save()
6.3.4 查
查询id为2的店铺下所有的商品类型
In [31]: s = Store.objects.get(id=2)
In [32]: s
Out[32]: <Store: 星星2号店>
In [33]: s.goodstypes.all()
Out[33]: <QuerySet [<GoodsType: 牛奶类>]>
查询类型1 的商品在哪家店铺出售
In [83]: gt = GoodsType.objects.get(id=1)
In [84]: gt.store_set.all()
Out[84]: <QuerySet [<Store: 星星1号店>, <Store: 星星4号店>]>
7、MVC和MVT架构模式
7.1 MVC架构模式
MVC全称Model View Controller,分为三个基本部分:模型Model、视图View和控制器Controller。
Model,模型,代表数据存取层,和数据库进行交互。
View ,视图,产生HTML页面,代表的是系统中选择显示什么和怎么显示的部分。
Controller,控制器, 接收请求,进行处理,与M和V进行交互,返回响应。
7.2 MVT架构模式
Django框架借鉴了MVC的思想,也分成三个部分来降低各个部分之间的耦合性,不同之处是Django框架分为三部分:Model模型、Template模板、View视图,这就是MVT模型。
Model(模型):负责业务对象与数据库的对象(ORM)。
View(视图):负责业务逻辑,并在适当的时候调用Model和Template。
Template(模版):负责如何把页面展示给用户。