ORM表操作

一、ORM配置

1.1 配置mysql数据库连接

setting文件里的DATABASES设置为

   DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'wangyong',    ## 数据库名称
        'USER': 'root',
        'PASSWORD': '123',   ## 安装 mysql数据库时,输入的root用户的密码
        'HOST': '127.0.0.1',
    }

 1.2 注册app

不要忘记在settings文件中的INSTALLED_APPS ​ 把你的app文件名加进去,否则无法识别到数据库。

如果创建Django项目时就自带了app,则无需注册

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
     'app01',   
]    

 1.3 设置pymysql连接(在任何的一个 __init__.py中都可以)

import pymysql
pymysql.install_as_MySQLdb()

 1.4 创建模型表(models.py)

class Class(models.Model):
    # id不用写, 自动生成 
    cname = models.CharField(max_length=32, null=True)

class Students(models.Model):
    # id不用写, 自动生成 
    sname = models.CharField(max_length=32, null=True)
    class_id_cname = models.ForeignKey('Class', null=True, on_delete=models.SET_NULL)
  
class Teachers(models.Model):
    tname = models.CharField(max_length=32, null=True)

class Teacheres_Classes(models.Model):
    id = models.AutoField(primary_key=True)
    cid_cname = models.ForeignKey('Class', null=True)
    tid_tname = models.ForeignKey('Teachers', null=True)
    class Meta:
        unique_together = (('cid_cname', 'tid_tname'),) 
class BaseModel(models.Model):
    """公共模型"""
    orders = models.IntegerField(verbose_name='显示顺序')
    is_show = models.BooleanField(verbose_name="是否上架", default=False)
    is_delete = models.BooleanField(verbose_name="逻辑删除", default=False)
    created_time = models.DateTimeField(verbose_name="创建时间", auto_now_add=True, null=True, blank=True)
    updated_time = models.DateTimeField(verbose_name="更新时间", auto_now=True, null=True, blank=True)
    class Meta:
        # 抽象模型,一般用于设置公共模型字段的,一旦设置这个相关以后,那么dajngo在数据迁移的时候就不会为这个模型单独创建一个数据表了
        abstract=True

1.5 生成表

1.5.1 方式一:快捷生成

1. 工具栏 Tools -->  run manage.py Task 

2. 在出现的manage.py@项目名称中依次输入

makemigrations
migrate

1.5.2 方式二:在Terminal中执行命令

python3 manage.py makemigrations   ## 生成migrations文件
python3 manage.py  migrate         ### 根据生成的migrations文件生成表

二、对单表的操作

 2.1 增

# 增加一条数据
    Class.objects.create(name="xxx")
    # 增加会有一个返回值,这个返回值就是这次插入的对象
    
# 增加多条数据
    obj = [
        Class(cname='pyton111'),
        Class(cname='pyton222'),
        Class(cname='pyton333'),
    ]
    Class.objects.bulk_create(obj)

2.2 删除

models.Classes.objects.filter(name="xxx").delete()

2.3 改

models.Classes.objects.filter(name="xxx").update(name="ooo")
    
# 如果需要改的值很多,并且在一个字典里,也可以用**打散
models.Classes.objects.filter(name="xxx").update(**dic)

2.4 普通查询

# 1、查询所有
    res = Class.objects.all() # QuerySet对象,(列表套对象)
    print(res) # <QuerySet [<Class: Class object>, <Class: Class object>, <Class: Class object>, <Class: Class object>]>
    for row in res:
        print(row.id, row.cname)

# 2. 指定字段查询 values, value_list
    res = Class.objects.values('cname').all() # QuerySet对象,(列表套字典)
    print(res) 
    res = Class.objects.values_list('cname').all()   # QuerySet对象,(列表套元组)
    print(res)   

# 3、filter 筛选
    res = Class.objects.filter(id=1).all()
    print(res)  # <QuerySet [<Class: Class object>]

# 4、大于,大于等于,小于,小于等于 __gt, __gte, __lt, __lte
    res = Class.objects.filter(id__lt=3)
    print(res)   # <QuerySet [<Class: Class object>, <Class: Class object>]>
    for row in res:
        print(row.id, row.cname)   

2.5 高级查询

# 1、in
    res = Class.objects.filter(id__in = [1,2,3])
    print(res) # <QuerySet [<Class: Class object>, <Class: Class object>, <Class: Class object>]>
    for row in res:
        print(row.id, row.cname)
    

# 2、 not in
    res = Class.objects.exclude(id__in=[1,2,3])
    print(res)   # <QuerySet [<Class: Class object>]>
    for row in res:
        print(row.id, row.cname)  

# 3、like
    # startswith, istartwith,(不区分大小写)  where name like 'py%' ## 以py开头的所有的数据
    # endswith, iendswith       where  name  like '%py'
    # contains, icontains      包含某一个单词    where name like "%py%"

    res = Class.objects.filter(cname__istartswith='py')
    print(res)  # <QuerySet [<Class: Class object>, <Class: Class object>, <Class: Class object>, <Class: Class object>]>
    for row in res:
        print(row.id, row.cname)

# 4、between ... and ..
    res = Class.objects.filter(id__range=[1,3])
    print(res)   # <QuerySet [<Class: Class object>, <Class: Class object>, <Class: Class object>]>

# 5、limit 10,20
    res = Class.objects.all()[0:3]   #[ 开始位置: 结束位置]
    print(res)   # <QuerySet [<Class: Class object>, <Class: Class object>, <Class: Class object>]>

# 6、order by age asc, name desc
    res = Class.objects.all().order_by('id', 'cname')   # 默认升序前面加一个 ‘-’ 代表 降序
    print(res.query)    # SELECT "app1_class"."id", "app1_class"."cname" FROM "app1_class" ORDER BY "app1_class"."id" ASC, "app1_class"."cname" ASC

# 7、group by
    from django.db.models import Count, Max, Min, Sum
    res = Class.objects.values('cname').annotate(xxx=Count('id'))
    print(res.query)   # SELECT "app1_class"."cname", COUNT("app1_class"."id") AS "xxx" FROM "app1_class" GROUP BY "app1_class"."cname"

# 8、only: 只取某一列值
    res = Class.objects.only('id', 'cname').all()
    print(res.query) # SELECT "app1_class"."id", "app1_class"."cname" FROM "app1_class"

# 9、defer: 除了这几列之外的所有值 (但是不管怎样, 都会查 id)
    res = Students.objects.defer('id','sname').all()
    print(res.query) # SELECT "app1_students"."id", "app1_students"."stu_cla_id" FROM "app1_students"

# 10、 using: 想要使用哪个数据库, 就将这个数据库的配置名称写到using中
    Class.objects.all().using('xxxx')

# 11、count 表中总共有多少条数据
    res = Class.objects.count()   # count不需要参数
    print(res)

# 12、第一条数据,最后一条数据
    res = Class.objects.first()
    ret = Class.objects.last()
    print(res, ret)  # Class object Class object

# 13、 gt 大于 gte: 大于等于   lt 小于   lte 小于等于
    res = Class.objects.filter(id__gt=2)
    print(res)    # <QuerySet [<Class: Class object>, <Class: Class object>]>

# 14、and操作
    res = Class.objects.filter(id=1,cname='pyton111')
    print(res)   # <QuerySet [<Class: Class object>]>
    print(res.query)   # SELECT "app1_class"."id", "app1_class"."cname" FROM "app1_class" WHERE ("app1_class"."id" = 1 AND "app1_class"."cname" = pyton8期)

# 15、or操作
    from django.db.models import Q
    res = Class.objects.filter(Q(id=2) | Q(cname='pyton111'))
    print(res.query)  # SELECT "app1_class"."id", "app1_class"."cname" FROM "app1_class" WHERE ("app1_class"."id" = 2 OR "app1_class"."cname" = pyton8期)

# 16、在原来的基础上更新值
    from django.db.models import  F
    UserInfo.objects.update(age=F('age') + 1)  # 表中存在可以需要更新的值,使用方式如此

# 17、原生sql
    # 方式一
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute("select * from app1_class where id=%s", [1,])
    res = cursor.fetchall()
    print(res)  #
    res = cursor.fetchone()
    print(res)

    # 方式二
    res= Class.objects.raw('select * from main.app1_class')
    print(res)   # <RawQuerySet: select * from main.app1_class>
    for row in res:
        print(row.id, row.cname)

三、一对多操作

 3.1 查

# 1、查询所有
    res = Students.objects.all()  # 列表套对象
    print(res)  # <QuerySet [<Students: Students object>, <Students: Students object>]>

# 2、查询一个
    res = Students.objects.first()
    print(res)   # Students object
    print(res.id, res.sname, res.stu_cla_id)  # 1 富强 1

# 3、正向查询
    res = Students.objects.all()
    for row in res:
        print(row.id, row.sname, row.stu_cla.cname)


# 4、 反向查询 外键关联的表名小写_set.filter()
    # 需求:查询所有课程下的所有学生姓名
    res = Class.objects.all()
    for row in res:
        print(row.cname, row.students_set.all())
        for k in row.students_set.all():
            print(row.cname, k.sname)


# 5、神奇的双下划线(跨表查询) (列表套字典)
    res = Students.objects.values('sname', 'stu_cla__cname')
    print(res)

 

四、多对多操作

 4.1 查

# 查询 老师 zeikai 所教的班级
# 方式一
    res = Teachers.objects.filter(sname='zekai').first()
    print(res.id, res.sname)   # 1 zekai
    tea_cla_list = res.teacherclass_set.all()
    print('tea_cla_list',tea_cla_list) # <QuerySet [<TeacherClass: TeacherClass object>, <TeacherClass: TeacherClass object>]>
    for obj in tea_cla_list:
        print(obj.cid.cname)
  

# 方式二
    res = TeacherClass.objects.filter(tid__sname='zekai').all()
    for obj in res:
        print(obj.cid.cname)
 

# 方式三
    res = TeacherClass.objects.filter(tid__sname='zekai').values('cid__cname')
    print(res)   

 

五、ORM的列数据类型

 

 

六、ORM中的参数

6.1 基础参数

max_length=32
null=True  : # 可以设置为null
db_index=True : # 设置索引
on_delete=models.CASCADE    # 设置级联删除
    SET_NULL : # 取消级联删除
default : # 设置默认值
unique : # 设置唯一索引
        
db_column: # 设置一个列名
    
unique_together: 联合唯一索引
index_together :普通联合索引
class Meta:
    unique_together = (
        ('money', 'us_id'),
          ....
    )
    index_together = (
         ('money', '')
           ....
     )

6.2 断关联多表关系

"""
1、外键位置:
    一对多 - 外键放多的一方
    一对一 - 从逻辑正反向考虑,如作者表与作者详情表,作者删除级联删除详情,详情删除作者依旧存在,所以建议外键在详情表中
    多对多 - 外键在关系表中
2.关联表之间断关系(全部写在外键字段的括号里)

    db_constraint=False, # 断关联
    related_name='books',  # 反向查询字段:publish_obj.books 就能访问所有出版的书(名字可随意取)
2、ORM正向方向连表查找:
    正向:通过外键字段 eg: author_detial_obj.author 
    反向:通过related_name的值 eg:author_obj.detail
    注:依赖代码见下方
    
3、连表操作级联关系(以作者表和详情表(外键在此表)一对一为例,写在外键字段括号里):
    1)级联删除:(作者删除,详情也删除);(详情删除,作者不删除) - on_delete=models.CASCADE
    2)作者删除,详情表外键字段值置空其他字段值不变 - null=True, on_delete=models.SET_NULL
    3)作者删除,详情表外键字段值重置为默认值 - default=0, on_delete=models.SET_DEFAULT
    4)作者删除,详情表对应那一整条信息不动 - on_delete=models.DO_NOTHING
    注:拿作者与作者详情表举例
    
4、外键关联字段的参数 - 如何实现 断关联、目前表间操作关系、方向查询字段
    i)作者详情表中的
    author = models.OneToOneField(
        to='Author',
        related_name='detail',
        db_constraint=False,
        on_delete=models.CASCADE
    )
    
    ii)图书表中的
    publish = models.ForeignKey(
        to='Publish',
        related_name='books',
        db_constraint=False,
        on_delete=models.DO_NOTHING,
    )
    authors = models.ManyToManyField(
        to='Author'
        related_name='books',
        db_constraint=False,
    )
    注:ManyToManyField不能设置on_delete,OneToOneField、ForeignKey必须设置on_delete(django1.x系统默认级联,但是django2.x必须手动明确)
"""

 

七、如何扩张auth_user表

 7.1 一对一关联(不推荐)

from django.contrib.auth.models import User
class UserDetail(models.Models):
    phone = models.CharField(max_length=11)
    user = models.OnoToOneField(to=User)

7.2 面向对象继承

from django.contrib.auth.models import User,AbstractUser
class UserInfo(AbstractUser):
    phone = models.CharField(max_length=32)

# 在settings中需要在配置文件中,指定我不再使用默认的auth_user表而是使用我自己创建的Userinfo表
AUTH_USER_MODEL = "app名.models里面对应的模型表名"

 

 

 

 

八、ORM的自关联

 

posted on 2020-03-31 15:28  软饭攻城狮  阅读(104)  评论(0编辑  收藏  举报

导航