Python(Web篇)---Django框架【三】数据库ORM模块--ORM操作


flask-sqlalchemy是对python三方的ORM sqlalchemy的封装,sqlalchemy是模仿Django的ORM编写,相较于Django ORM,sqlalchemy的操作比较复杂,但是迁移性比Django的ORM好。

一、基本操作

django 为了开发者学习或者测试使用orm,提供了交互式界面
python manage.py shell 进入含有当前项目结构的shell模式

(D:\Anaconda3\envs\D_37) F:\0831Pro\DjPro\Qshop>python manage.py shell
Python 3.7.9 (default, Aug 31 2020, 17:10:11) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from Goods.models import Goods
>>>

(一)增

上次我们已经创建了数据库,但库中没有任何数据。
添加数据步骤:

  1. 实例化一个表对象
  2. 添加相关信息
  3. 提交至数据库
>>> from Goods.models import Goods
>>> Goods.objects.create(g_name = "张家口黄瓜",g_price = 18.1,g_old_price = 18.1,g_public = "1991-12-22",g_
number = 34,g_store = "天天生鲜",save_time=5,save_unit="纪元",del_flag="False")
<Goods: Goods object (2)>
>>> from Goods.models import Goods
>>> Goods.objects.create(g_name = "张家口黄瓜",g_price = 18.1,g_old_price = 18.1,g_public = "1991-12-22",g_
number = 34,g_store = "天天生鲜",save_time=5,save_unit="纪元",del_flag="False")
<Goods: Goods object (2)>
>>> g = Goods()
>>> g.g_name = "少林寺烤鸭"
>>> g.g_price = 88.88
>>> g.g_old_price = 8.88
>>> g.g_public = "1883-2-1"
>>> g.g_number = 1
>>> g.g_store = "天天生鲜"
>>> g.save_time = 15
>>> g.save_unit = "秒"
>>> g.del_flag = "False"
>>> g.save()

简单的只有几条数据的数据库对我们来说显然是不够的,也起不到很好的学习作用,我们需要大量的数据进行练习,至少是上万条甚至是数十万条,此时就要使用批量添加数据操作。

在pycharm中批量添加数据

import random

from Goods.models import Goods
def add_goods(request):
    foods = "五花肉、里脊肉、猪蹄、蹄髈、大排、小排、肉丝、肉末、夹心肉、猪尾、猪心、金针菇、香菇、锦绣菇、蘑菇、杏鲍菇、百灵菇、菠菜、青菜、鸡毛菜、娃娃菜、大白菜、芹菜、西芹、茼蒿、米苋、香菜、生菜、包菜、花椰菜、西兰花、紫甘蓝、凤尾菜、草头、虎皮青椒、菜椒、青红椒、莴笋、山药、芋艿、土豆、冬瓜、南瓜、萝卜、胡萝卜、莲藕、茭白、竹笋、冬笋、红薯、紫薯、花生、玉米、蒜台、秋葵、芥兰、芦笋、西红柿、金针菇、香菇、锦绣菇、蘑菇、杏鲍菇、百灵菇、老姜、嫩姜、大葱、大蒜、小米椒、洋葱".split(
        "、")
    address = "石河子、阿拉尔市、图木舒克、五家渠、哈密、吐鲁番、阿克苏、喀什、和田、伊宁、塔城、阿勒泰、奎屯、博乐、昌吉、阜康、库尔勒、阿图什、乌苏、呼和浩特、包头、乌海、赤峰、通辽、鄂尔多斯、呼伦贝尔、巴彦淖尔、乌兰察布、南宁、柳州、桂林、梧州、北海、崇左、来宾、贺州、玉林、百色、河池、钦州、防城港、贵港、石家庄、唐山、邯郸、秦皇岛、保定、张家口、承德、廊坊、沧州、衡水、邢台、辛集市、藁城市、晋州市、新乐市、鹿泉市、遵化市、迁安市、武安市、南宫市、沙河市、涿州市、定州市、安国市、高碑店市、泊头市、任丘市、黄骅市、河间市、霸州市、三河市、冀州市、深州市、广州、深圳、汕头、惠州、珠海、揭阳、佛山、河源、阳江、茂名、湛江、梅州、肇庆、韶关、潮州、东莞、中山、清远、江门、汕尾、云浮".split(
        "、")
    for i in range(10000):
        g = Goods()
        g.g_name = random.choice(address)+random.choice(foods)
        g.g_price = random.randint(1,1000)*0.3
        g.g_old_price = random.randint(1,1000)*0.3
        g.g_public = "{}-{}-{}".format(
            random.randint(1000,3000),
            random.randint(1, 12),
            random.randint(1, 28),
        )
        g.g_number = random.randint(500, 10000)
        g.g_store = random.choice(["天天生鲜","生活超市","兴隆餐馆"])
        g.save_time = random.randint(1,12)
        g.save_unit = random.choice(["年","月","日"])
        g.del_flag = random.choice(["True","False"])
        g.save()
    return render_to_response("index.html")

(二)查(重点)

1. 查询所有 all()

>>> from Goods.models import Goods
>>> Goods.objects.all()
<QuerySet [张家口西红柿, 张家口黄瓜, 少林寺烤鸭, 南宁杏鲍菇, 钦州冬笋, 奎屯芦笋, 崇左紫薯, 呼伦贝尔洋葱, 沧
州娃娃菜, 百色肉末, 遵化市菜椒, 梧州杏鲍菇, 河间市西芹, 鄂尔多斯青菜, 清远芥兰, 乌海西芹, 乌苏百灵菇, 惠州
大白菜, 张家口五花肉, 昌吉杏鲍菇, '...(remaining elements truncated)...']>
>>> len(Goods.objects.all())
10003

2. 顺序查询 order_by()

Goods.objects.order_by("g_price") 从小到大
Goods.objects.order_by("-g_price") 从大到小 倒序

3. 查询部分 filter

filter支持多个条件,但是多个条件按照and关系处理

查询所有张家口金针菇

>>> for i in Goods.objects.filter(g_name="张家口金针菇"):
...     print("{}:{}".format(i.g_name,i.g_price))
...
张家口金针菇:230.1
张家口金针菇:103.5
张家口金针菇:189.29999999999998

查询所有天天生鲜销售的库尔勒金针菇

>>> for i in Goods.objects.filter(g_name="库尔勒金针菇",g_store="天天生鲜"):
...     print("{}:{}".format(i.g_name,i.g_price))
...
库尔勒金针菇:42.6
库尔勒金针菇:249.0

django当中的filter查询条件不可以直接使用 > < 等其他方法,所以编写了很多私有方法

方法描述
__contains模糊查询,相当like(%查询条件%)
__lt小于
__gt大于
__lte小等于
__gte大等于
__in包含
__isnull值为null
__startwith以啥开头的

例:
查询所有张家口的生鲜

Goods.objects.filter(g_name__contains="张家口")

查询价格小于100块的生鲜

Goods.objects.filter(g_price__lt=100)

查询所有500到700数量的商品

Goods.objects.filter(g_number__in = range(500,701))

4. 查询一条

方法描述
get使用唯一条件查询,返回具体的一条数据,不是query_set对象
firstqueryset对象的第一条
lastqueryset对象的最后一条

注:get方法返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
例:

>>> Goods.objects.get(id=1)
张家口西红柿
>>> Goods.objects.all().first()
张家口西红柿
>>> Goods.objects.all().last()
呼和浩特茼蒿
>>>

5. 聚合查询

导包:from django.db.models import Sum,Avg,Max,Min,Count
依赖:aggregate是Django ORM中的终止语句

>>> from django.db.models import Sum,Avg,Max,Min,Count
查询张家口蔬菜的个数
>>> Goods.objects.filter(g_name__contains="张家口").aggregate(Count("id"))
{'id__count': 98}
查询张家口蔬菜的最高价格
>>> Goods.objects.filter(g_name__contains="张家口").aggregate(Max("g_price"))
{'g_price__max': 297.0}
查询张家口蔬菜的最低价格
>>> Goods.objects.filter(g_name__contains="张家口").aggregate(Min("g_price"))
{'g_price__min': 1.2}
查询张家口蔬菜的平均价格
>>> Goods.objects.filter(g_name__contains="张家口").aggregate(Avg("g_price"))
{'g_price__avg': 144.29897959183674}
查询张家口蔬菜的总价
>>> Goods.objects.filter(g_name__contains="张家口").aggregate(Sum("g_price"))
{'g_price__sum': 14141.3}

6. 分组查询:annotate()

查询每个店铺的生鲜的个数
>>> Goods.objects.all().values("g_store").annotate(Count("id"))
<QuerySet [{'g_store': '兴隆餐馆', 'id__count': 2458}, {'g_store': '生活超市', 'id__count': 2491}, {'g_store': '天天生鲜', 'id__count': 2538}]>
查询每个生鲜店铺的均价
>>> Goods.objects.all().values("g_store").annotate(Avg("g_price"))
<QuerySet [{'g_store': '兴隆餐馆', 'g_price__avg': 151.42652563059386}, {'g_store': '生活超市', 'g_price__avg': 153.33480529907683}, {'g_store': '天天生
鲜', 'g_price__avg': 149.10720252167064}]>

7. F查询

用来进行同一个模型中两个字段间的比较

例:
查询所有降价的商品

Goods.objects.filter(g_price__lt = F("g_old_price"))

8. Q查询

filter()等的关键字参数指定的条件是并联(and)在一起的,如果需要执行更复杂的查询(or,not),可以使用Q查询

Goods.objects.filter(Q(g_store = "天天生鲜")|Q(g_store = "兴隆餐馆")) 查询天天生鲜或兴隆餐馆的生鲜
Goods.objects.filter(~Q(g_store = "兴隆餐馆")) 查询所有非兴隆餐馆的生鲜
逻辑符号逻辑关系
|or 或
&and 且
~not 非

(三)删

使用delete方法

  1. 类名.objects.get(xxx).delete()
  2. 类名.objects.filters(xxx).delete()
>>> from Goods.models import Goods
>>> g = Goods.objects.get(id=1)
>>> g
张家口西红柿
>>> g.delete()
(1, {'Goods.Goods': 1})
>>>

(四)改

  1. 使用update方法
    类名.objects.filters(xxx).update().update(name=xxx)
  2. 使用save方法亦可达到修改效果
g = Goods.objects.get(id=2)
>>> g.update(g_name = "张家口苦瓜")
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'Goods' object has no attribute 'update'
>>> g.g_name = "张家口苦瓜"
>>> g.save()
>>>

k = Goods.objects.filter(id=2)
k.update(g_name="张家口甜瓜")

注意:update方法只能基于queryset对象使用,也就是只能批量修改

二、关系操作

(一)一对一关系 OneToOneField

  1. 关系搭建
    例:账户和用户详情一对一
class User(models.Model):
    username = models.CharField(max_length = 32)
    password = models.CharField(max_length = 32)

class UserInfo(models.Model):
    nick_name = models.CharField(max_length = 32)
    user = models.OneToOneField(to = User,on_delete = models.CASCADE) #on_delete 删除的模式,CASCADE 级联删除
  1. 插入数据
>>> from Goods.models import User,UserInfo
>>> u = User()   # 插入用户
>>> u.username = "张三"
>>> u.password = "123"
>>> u.save()

>>> ui = UserInfo()    # 插入用户详情
>>> ui.nick_name = "阿三"
>>> ui.user = u
>>> ui.save()
  1. 查询

有一对一关系字段就用字段查询,没有字段使用表名小写查询。

# 查询用户的详情
>>> from Goods.models import User,UserInfo
>>> u = User.objects.get(id=1)
>>> u.username
'张三'
>>> u.userinfo
<UserInfo: UserInfo object (1)>
>>> u.userinfo.nick_name
'阿三'
>>>

# 查询详情的用户名
>>> ui = UserInfo.objects.get(id = 1)
>>> ui.user
<User: User object (1)>
>>> ui.user.username
'张三'

(二)一对多关系 ForeignKey

  1. 关系搭建
    例:学生和教室之间的多对多
class ClassRoom(models.Model):
    r_number = models.CharField(max_length=32)

class Student(models.Model):
    s_name = models.CharField(max_length = 32)
    s_room = models.ForeignKey(to = ClassRoom,on_delete = models.CASCADE) #外键字段
  1. 插入数据
#  插入教室
>>> from Goods.models import Student,ClassRoom
>>> c = ClassRoom()
>>> c.r_number = "1-2048"
>>> c.save()

# 插入学员
>>> s = Student()
>>> s.s_name = "小明"
>>> s.s_room = c
>>> s.save()

>>> s = Student()
>>> s.s_name = "小红"
>>> s.s_room = c
>>> s.save()
  1. 数据查询
    有外键字段用外键字段,没有外键字段,表名小写_set
# 教室里所有的学员
>>> c.student_set
<django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager obj
ect at 0x000001938893F708>
>>> c.student_set.all()  # student(学员表名小写)_set构成一表查多表
<QuerySet [<Student: Student object (1)>, <Student: Student object (2)>]>


# 查询学员对应的教室
>>> s = Student.objects.get(id = 1)
>>> s.s_room
<ClassRoom: ClassRoom object (1)>
>>> s.s_room.r_number
'1-2048'

(三)多对多关系 ManyToManyField

  1. 关系搭建
    例:班级与老师的多对多
class ClassLevel(models.Model):
    c_name = models.CharField(max_length = 32)

class Teacher(models.Model):
    t_name = models.CharField(max_length = 32)
    t_class = models.ManyToManyField(to = ClassLevel)
  1. 添加数据
>>> from Goods.models import ClassLevel
>>> from Goods.models import Teacher

# 添加班级
>>> c = ClassLevel()
>>> c.c_name = "Python_0831"
>>> c.save()

# 添加老师
>>> t = Teacher()
>>> t.t_name = "王老师"
>>> t.save()
>>> t.t_class.add(c)
>>> t.save()

>>> t = Teacher()
>>> t.t_name = "李老师"
>>> t.save()
>>> t.t_class.add(c)
>>> t.save()
  1. 查询数据
# 查询班级所有的任课老师
>>> c = ClassLevel.objects.get(id = 1)
>>> c
<ClassLevel: ClassLevel object (1)>
>>> c.teacher_set.all()
<QuerySet [<Teacher: Teacher object (1)>, <Teacher: Teacher object (2)>]>
>>> [t.t_name for t in c.teacher_set.all()]
['王老师', '李老师']

# 查询老师带过的班级
>>> t = Teacher.objects.get(id = 1)
>>> t.t_class
<django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManage
r object at 0x000001A162178C08>
>>> t.t_class.all()
<QuerySet [<ClassLevel: ClassLevel object (1)>]>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值