Django基础知识 数据库操作

目录

1 ORM简介

2 创建表

3 操作表

3.1 增

3.2 删       

3.3 改 

3.4 查

3.5 查询条件之双下划线

3.6 关联表查询

3.7 聚合查询和分组查询

3.8 F查询和Q查询

4 惰性机制

5 admin使用

5.1 简介

5.2 文件配置

6 其他

6.1 settings.py增加日志记录部分,记录执行的SQL语句


1 ORM简介

ORM:对象关系映射(Object Relationl Mapping),用面向对象的方式去操作数据库的表,实现面向对象编程语言里不同类型系统的数据之间的转换。

优点:不用写复杂的SQL语句,避免新手写SQL带来的性能问题。

缺点:性能有所牺牲。

# 通过QuerySet的query属性查询对应操作的SQL语句
obj = models.Author.objects.filter(id = 1)
print(obj.query)

2 创建表

在Django项目的models.py文件中通过创建类来创建表。

一对一(OneToOneField):一般用于某张表的补充,可以方便的从子表查询母表信息或反向查询。

一对多(ForeignKey):创建一对多关系,比如一个班级有多个学生,则在学生表中创建关联到班级的一对多外键(学生表中创建cls = models.ForeignKey(),系统会生成cls_id字段);django2.0及以上版本在使用OneToOneField和ForeignKey时,需要加上on_delete参数。

多对多(ManyToManyField):创建多对多关系,比如一个班级有多位老师,一个老师教多个班级,则在其中任一表中创建多对多字段,系统会默认创建包含多对多关系的第三张表;也可以通过手动创建第三张关系表的方式建立多对多关系,但不能使用add、remove方法。

from django.db import models


class Students(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
# 建立Students和Classes的一对多关系
    cls = models.ForeignKey('Classes', on_delete=models.CASCADE)

    def __str__(self):
        return self.name


class Classes(models.Model):
    name = models.CharField(max_length=100)
# 建立Classes和Teachers的多对多关系
    teach = models.ManyToManyField('Teachers')

    def __str__(self):
        return self.name


class Teachers(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name


# 手动创建多对多关系表
class MyClassesToTeachers(models.Model):
    classes = models.ForeignKey('Classes', on_delete=models.CASCADE)
    teachers = models.ForeignKey('Teachers', on_delete=models.CASCADE)
# 创建联合唯一约束,根据实际需求添加此项
    class Meta:
        unique_together = ['classes', 'teachers']

3 操作表

3.1 增

# 增加数据 方式1
models.Students.objects.create(name='张三', age=18)

# 增加数据 方式2
models.Students.objects.create(**{'name': '李四', 'birth': 18})

# 增加数据 方式3
student = models.Students(name='王五', birth=81)
student.save()

# 增加数据 方式4
student = models.Students()
student.name = '刘国庆'
student.age = 50
student.save()

# 一对多表中增加数据,示例Students表中创建了关联到Classes表的外键cls
models.Students.objects.create(name='张三1', age=18, cls_id=1)

# 一对多表中增加数据,示例Students表中创建了关联到Classes表的外键cls
class1 = models.Classes.objects.filter(id=1)
models.Students.objects.create(name='张三2', age=18, cls=class1[0])

# 多对多表中增加数据(正向),示例Classes表中创建了关联到Teachers表的多对多字段teach
teacher1 = models.Teachers.objects.filter(id=1)[0]
teacher2 = models.Teachers.objects.filter(id=2)[0]
class1 = models.Classes.objects.filter(id=1)[0]
class1.teach.add(teacher1, teacher2)

# 多对多表中增加数据(反向),示例Classes表中创建了关联到Teachers表的多对多字段teach
teacher = models.Teachers.objects.filter(id=1)[0]
classes = models.Classes.objects.filter(id__gt=1)
teacher.classes_set.add(*classes)

3.2 删       

# 方式1 delete() 级联删除,同时删除关系
obj = models.Students.objects.filter(id=1).delete()
print(obj)
# 打印内容 (1, {'app01.Students': 1})
obj = models.Teachers.objects.filter(id=1).delete()
print(obj)
# 打印内容 (3, {'app01.Classes_teacher': 2, 'app01.Teachers': 1}) 同时删除了关系表中的2条关系数据

#方式2 remove()
teacher = models.Teachers.objects.filter(id=1)[0]
classes = models.Classes.objects.filter(id__gt=0)
teacher.classes_set.remove(*classes)

#方式3 clear() 清空

3.3 改 

# 修改数据 方式1
student = models.Students.objects.get(id=1)
student.name = '王三'
student.save()

# 修改数据 方式2
models.Students.objects.filter(id=1).update(name='李三')

# 修改数据 方式3 .set()

注意:

1 save()方法会更新一行里的所有列。

2 get()方法返回的是model对象,没有update方法;filter()返回的是QuerySet对象可以调用update()方法。

3.4 查

1 filter(**kwargs)

obj = models.Students.objects.filter(cls_id=1)
print(obj)
# 打印结果
<QuerySet [<Students: 李三>, <Students: 李四>, <Students: 张国庆>]>

2 all()

obj = models.Students.objects.all()
print(obj)
# 打印结果
<QuerySet [<Students: 李三>, <Students: 李四>, <Students: 王五>, <Students: 张国庆>]>

3 get(**kwargs) 返回一个model对象,符合筛选结果的对象超过1个或者没有都会报错。

obj = models.Students.objects.get(id=1)
print(obj)
# 打印结果
李三

4 values(*field) 返回一个字典序列。

obj = models.Students.objects.filter(age=18).values('name')
print(obj)
# 打印结果
<QuerySet [{'name': '李三'}, {'name': '李四'}]>

5 values_list(*field) 返回一个元组序列。

obj = models.Students.objects.filter(age=18).values_list('name')
print(obj)
# 打印结果
<QuerySet [('李三',), ('李四',)]>

6 exclude(**kwargs) 返回与筛选条件不符合的对象。

obj = models.Students.objects.exclude(id=1)
print(obj)
# 打印结果
<QuerySet [<Students: 李四>, <Students: 王五>, <Students: 张国庆>]>

7 order_by(*field) 对查询结果排序,加负号则是反向排序。

obj = models.Students.objects.order_by('-age')
print(obj)
# 打印结果
<QuerySet [<Students: 王五>, <Students: 张国庆>, <Students: 李三>, <Students: 李四>]>

8 reverse() 对查询结果反向排序。

9 distinct() 从返回结果中剔除重复记录。

10 count() 返回数据库中匹配查询(QuerySet)的对象数量。

obj = models.Students.objects.filter(age=18)
print(obj.count())
# 打印结果
2

11 first() 返回第一条记录。

obj = models.Students.objects.filter(age=18).first()
print(obj)
# 打印结果
李三

12 last() 返回最后一条记录。

13 exists() 如果QuerySet包含数据就返回True,否则返回False。

3.5 查询条件之双下划线

以下示例基于下表:依次是Students、Classes、Teachers。

1 id__gt 大于,id__lt 小于,id__gte 大于等于,id__lte 小于等于。

obj = models.Students.objects.filter(id__gt=1, id__lte=4)
print(obj)
# 打印结果
<QuerySet [<Students: 李四>, <Students: 王五>, <Students: 张国庆>]>

2 id__in 匹配对应id值的数据。

obj = models.Students.objects.filter(id__in=[1, 3, 4])
print(obj)
# 打印结果
<QuerySet [<Students: 李三>, <Students: 王五>, <Students: 张国庆>]>

3 name__contains 匹配包含对应字符的数据,name__icontains不区分大小写。

obj = models.Students.objects.filter(name__contains='张')
print(obj)
# 打印结果
<QuerySet [<Students: 张国庆>, <Students: 张三1>, <Students: 张三2>, <Students: 张三2>]>

4 id__range 匹配对应范围内的数据。

obj = models.Students.objects.filter(id__range=[1, 4])
print(obj)
# 打印结果
<QuerySet [<Students: 李三>, <Students: 李四>, <Students: 王五>, <Students: 张国庆>]>

5 name__startwith,name__endwith,name__istartwith,name__iendwith 匹配以对应字符开头、结尾的数据。

3.6 关联表查询

# 获取pathon一班的老师名字
names = models.Teachers.objects.filter(classes__name='python一班').values('name')
print(names)
# 打印结果
<QuerySet [{'name': '张老三'}, {'name': '王老四'}]>

3.7 聚合查询和分组查询

aggregate(*args,**kwargs): 返回一个聚合值的字典,aggregate()中的每一个参数都制定一个包含在字典中的返回值。

annotate(*args,**kwargs):查询每个对象所关联的结果集合。

from django.db.models import Avg, Max, Min, Sum



ret = models.Students.objects.aggregate(Avg('age'), Max('age'), minimum_age=Min('age'))
print(ret)
# 打印结果 minimum_age=Min('age')可以指定返回值中的键名称
{'minimum_age': 18, 'age__avg': 31.5714, 'age__max': 81}

# 查询python一班所有学生的平均年龄
ret = models.Students.objects.filter(cls__name='python一班').aggregate(Avg('age'))
print(ret)
# 打印结果
{'age__avg': 18.0}

# 查询每个班级的平均年龄,以values()的结果进行分组并计算每个对象的统计结果
ret = models.Students.objects.values('cls__name').annotate(Avg('age'))
print(ret)

# 打印结果
<QuerySet [{'cls__name': 'python一班', 'age__avg': 18.0}, {'cls__name': 'python二班', 'age__avg': 65.5}]>

3.8 F查询和Q查询

from django.db.models import F, Q


# F:取某列的值进行操作
models.Students.objects.all().update(age=F('age')+1)

# Q:将单个条件包装成Q对象,通过逻辑运算符组合构造复杂的查询条件
# Q对象与关键字参数一起使用时,Q对象必须放在关键字参数的前面
obj = models.Students.objects.filter(Q(id__gt=1) & Q(age__lt=60) | ~Q(cls__name='python一班'))
print(obj)
# 打印结果
<QuerySet [<Students: 李四>, <Students: 王五>, <Students: 张国庆>, <Students: 张三1>, <Students: 张三2>, <Students: 张三2>]>

4 惰性机制

models.Students.objects.filter()等方法只是返回了一个QuerySet对象,它并不会马上执行SQL,而是当调用QuerySet的时候才执行。

QuerySet特点:可迭代,可切片

objs = models.Students.objects.all()
for obj in objs:
    print(obj)
# 打印结果
李三
李四
王五
张国庆

objs = models.Students.objects.all()
print(objs[1:2])
# 打印结果
<QuerySet [<Students: 李四>]>

5 admin使用

5.1 简介

admin是Django提供的一个后台管理app

5.2 文件配置

# 终端
# 第1步 迁移数据库
python manage.py makemigrations
python manage.py migrate
# 第2步 创建用户名、密码
python manage.py createsuperuser
# 第3步 启动服务器
python manage.py runserver 8000

# 浏览器
# 第4步 浏览器访问http://127.0.0.1:8000/admin 输入账号、密码登录!
# admin.py文件配置

from app01.models import *


# ModelAdmin是管理界面的定制类,如需扩展特定的model界面需从该类继承
class Myadmin(admin.ModelAdmin):
# 设置显示字段
    list_display = ('name', 'age', 'cls')
# 设置搜索字段
    search_fields = ('name',)
# 设置过滤器
    list_filter = ('name',)
# 设置排序字段
    ordering = ('-id',)


# 注册model类到anmin
admin.site.register(Students, Myadmin)
# 字段设置
# verbose_name 设置字段的显示内容,如将‘name’显示为‘书名’
# editable 设置是否可编辑,默认为True
name = models.CharField(max_length=100, verbose_name='书名', editable=False)

6 其他

6.1 settings.py增加日志记录部分,记录执行的SQL语句

# settings.py中添加代码
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level': 'DEBUG',
        },
    },
}

# views.py
objs = models.Teachers.objects.filter(id__gt=0)
for obj in objs:
    print(obj)
# 执行结果
(0.000) SELECT `app01_teachers`.`id`, `app01_teachers`.`name` FROM `app01_teachers` WHERE `app01_teachers`.`id` > 0; args=(0,); alias=default
张老三
王老四
# 执行第一遍for循环时会将数据放入缓存,之后每次循环都在缓存内取数据;为避免缓存中放入大量数据,使用迭代器......(待补充)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值