文章目录

  • ORM
  • 简介
  • 使用ORM
  • Django中连接数据库的配置
  • 操作数据表(表结构)
  • 操作数据
  • 增,删,改
  • 根据结果分类
  • 进阶方法 - 单表的双下划线
  • 外键
  • 表结构
  • 外键查询
  • 基于对象的正向查询
  • 基于QuerySet的正向查询(双下划线正向查询)
  • 基于对象的反向查询
  • 基于QuerySet的反向查询(双下划线反向查询)
  • 多对多
  • 表结构
  • 多对多查询
  • 基于对象的正向查询
  • 基于QuerySet的正向查询
  • 基于对象的反向查询
  • 基于QuerySet的反向查询
  • 增加



ORM

简介

全称 Object Relational Mapping, 对象关系映射
	类		-->		数据表
	属性 	-->		字段
	对象		-->		数据行

使用ORM

Django中连接数据库的配置

  • projectDir/__init__.py
"""
修改 django 连接 mysql 的模块为 pymysql
"""

import pymysql
pymysql.install_as_MySQLdb()
  • settings.py
# 数据库配置
DATABASES = {
    'default': {
        # 使用sqlit3
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),

        # 使用mysql
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'yky',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': 'xxxxxx',
    }
}

操作数据表(表结构)

  • models.py
"""
django会在person前添加"appName_"
创建appName_person表
"""

class Person(models.Model):
    id = models.AutoField(primary_key=True) # 主键
    name = models.CharField(max_length=32) # 最大长度32
    age = models.IntegerField() # 最大长度为10


"""
常用字段
-------
字符串类型					CharField
自增类型						AutoField
时间类型						DateField, DataTimeField, TimeField
最大长度为 10 的数字类型		IntergeField

常用参数
-------
数据可为空					null = True
admin 操作可留空				blank = True
默认值为 0					default = 0
数据唯一						unique = True
第一次创建时, 更新该字段		auto_now_add = True    
每次数据被修改时, 更新该字段	auto_add=True        

"""
  • 命令行
# 需要在项目目录下执行
cd $projectDir

# 将变化都记录下来
python manage.py makemigrations

# 转换为sql语句, 并执行
python manage.py migrate

操作数据

增,删,改

"""
增
字段需要写全
向Person表中添加name为u1, age为16的数据
"""
models.Person.objects.create(name='u1', age=16)


"""
删
先找再删
删除name为u1的数据
"""
models.Person.objects.get(name='u1').delete()


"""
改
先找到对应数据, 保存为对象, 修改对象的属性, 同步到数据库
将 name 从 u1 修改为 new_u1
"""
obj = models.Person.objects.get(name='u1')
obj.name = 'new_u1'
obj.save()

""" 1. 查询所有 """
# 常用语 list 展示
models.Person.objects.all()

""" 2. 根据条件查询 """
# 常用, 返回一个QuerySet列表
models.Person.objects.filter(id=2) 
# 根据查询条件获取一个唯一的值, 不唯一或者无匹配都会报错, 慎用 
models.Person.objects.get(id=2) 

""" 3. 返回查询结果的多个字段 """
# 返回一个QuerySet,里面是字典
models.Person.objects.filter(id=2).values('name','age')
# 返回一个QuerySet,里面是元祖
models.Person.objects.filter(id=2).values_list('name','age')

""" 4. 返回第一个或最后一个 """
# 取第一个数据
models.Person.objects.filter(id=2).first() 
# 取最后一个数据
models.Person.objects.filter(id=2).last()

""" 5. 对查询结果做处理 """
# 将符合条件的都剔除掉,留下不符合条件的
models.Person.objects.filter(age=18).exclude(id=10)
# 对查询结果排序
models.Person.objects.filter(age=18).order_by('age')
# 对一个有序的查询结果集做反转
models.Person.objects.filter(age=18).reverse()
# 去重,跨表查询时去掉重复的记录,MySQL不支持按字段去重
models.Person.objects.filter(age=18).distinct()

""" 6. 返回查询信息 """
# 返回数据条数
models.Person.objects.filter(age=18).count()
# 判断数据是否存在
models.Person.objects.filter(age=18).exists()

根据结果分类

# 返回 QuerySet
all(), filter(), exclude()
order_by(), reverse(), distinct()
values(), values_list()

# 返回具体对象
first(), last(), get()

# 返回数字
count()

# 返回布尔值
exists()

进阶方法 - 单表的双下划线

""" id小于10, 大于1 """
models.Person.objects.filter(id__lt=10, id__gt=1)

""" 获取id等于11、22、33的数据 """
models.Person.objects.filter(id__in=[11, 22, 33])   
""" not in """
models.Person.objects.exclude(id__in=[11, 22, 33])

""" 获取name字段包含"ven"的 """
models.Person.objects.filter(name__contains="ven") 
""" 不区分大小写 """
models.Person.objects.filter(name__icontains="ven")

""" id范围是1到3的,类似于sql中的"bettwen 1 and 3" """
models.Person.objects.filter(id__range=[1, 3])   

""" startwith, endwith """
models.Person.objects.filter(name__startwith='张')

""" date字段, birthday字段, 2018年的结果 """
models.Person.objects.filter(birthday__year=2018)

外键

表结构

""" 一般是已知学生, 查学校, 所以外键在学生方创建 """

# vim models.py

class Person(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField(max_length=3)
    school = models.ForeignKey(to="School", on_delete=models.CASCADE) # 级联删除, 2.0后需要手动指出, 1.11默认为此设置


class School(models.Model):
    name = models.CharField(max_length=32)

外键查询

基于对象的正向查询
# 找到第一个学生
person_obj = models.Person.objects.first()

# 学生.school(外键字段).name(查询的外键字段)
school_name = person_obj.school.name

基于QuerySet的正向查询(双下划线正向查询)
# 得到一个QuerySet
qs = models.Person.objects.all()

# 使用 "外键字段__查询字段"
ret = qs.values_list("school__name")

基于对象的反向查询
# 找到id为2的学校
school_obj = models.School.objects.get(id=2)

# 学校.查询表名_set
ret = school_obj.person_set.all()

基于QuerySet的反向查询(双下划线反向查询)
# 得到QuerySet
qs = models.School.objects.filter(id=1)

# 使用 "查询表__查询字段"
ret = qs.values_list("book__name")

多对多

一个人可以会很多种语言, 一种语言也有很多人会
"多对多的关系"

表结构

class Person(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    school = models.ForeignKey(to="School", on_delete=models.CASCADE)
    language = models.ManyToManyField(to="Language", related_name='ooo')


class School(models.Model):
    name = models.CharField(max_length=32)


class Language(models.Model):
    name = models.CharField(max_length=32)

多对多查询

基于对象的正向查询
# 获取正向查询对象
person_obj = models.Person.objects.first()

# 对象.多对多的字段, 结果为QuerySet
data = person_obj.language

# 再使用values()/values_list()/all()处理QuerySet
ret = data.values_list('name')
ret = data.all()
基于QuerySet的正向查询
# 获取QuerySet
data = models.Person.objects.filter(id=1)

# 处理QuerySet, "查询表__查询字段"
ret = data.values('language__name')

基于对象的反向查询
# 获取反向查询对象
language_obj = models.Language.objects.last()

# 对象.表名_set, 结果为QuerySet
ret = language_obj.person_set

# 如果models中设置了related_name属性(related_name设定为ooo)
ret = language_obj.ooo

# 最后使用values()/values_list()/all()做处理
ret = data.values_list('name')
ret = data.all()
基于QuerySet的反向查询
# 获取QuerySet
data = models.Language.objects.filter(id=1)

# 处理QuerySet, "related_name__查询字段"
ret = data.values('ooo__name')

增加

当form表单提交的数据是列表(多选的select/多选的checkbox)时
使用request.POST.getlist("hobby")
# 参数是一个列表, 重新赋值
.set([i1, i2, i3]) 

# 参数是一个值, 添加新值
.add(i4)
"""
用户提交了
	username = u1
	language = ['英语','日语']
"""

# 先创建对象
user_obj = models.Person.objects.create(name=username)
# 设置对象
user_obj.language.set(language)