zoukankan      html  css  js  c++  java
  • day52:django:ORM单表/多表操作

    目录

    1.ORM

    2.ORM单表增删改查

      13个必知必会的查询接口

      filter基于双下划线的模糊查询

    3.ORM多表增删改查

    ORM

    什么是ORM?

    ORM(object relational mapping) 对象关系映射,做数据库操作的

    ORM中的对象关系映射

    ORM的实际使用

    1.首先,我们在django项目的app01/models.py中写入如下内容

    class Book(models.Model):
        # id 这行可写可不写,如果不写的话,系统也会自动添加上去
        id = models.AutoField(primary_key=True) # id int primary key auto_increment,
        title = models.CharField(max_length=32)  # title varchar(32)
        price = models.DecimalField(max_digits=5,decimal_places=2)  #price decimal(5,2)  999.99
        pub_date = models.DateField()  # pub_date date
        publish = models.CharField(max_length=32)

    2.执行数据库同步指令,在项目根目录下面执行

    python manage.py makemigraitons
    python manage.py migrate

    Tip:查看FIeld和mysql中的字段关系对比

    C:ProgramDataAnaconda3Libsite-packagesdjangodbackendsmysqlase.py

    具体内容大致如下

       _data_types = {
            'AutoField': 'integer AUTO_INCREMENT',
            'BigAutoField': 'bigint AUTO_INCREMENT',
            'BinaryField': 'longblob',
            'BooleanField': 'bool',
            'CharField': 'varchar(%(max_length)s)',
            'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
            'DateField': 'date',
            'DateTimeField': 'datetime',
            'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
            'DurationField': 'bigint',
            'FileField': 'varchar(%(max_length)s)',
            'FilePathField': 'varchar(%(max_length)s)',
            'FloatField': 'double precision',
            'IntegerField': 'integer',
            'BigIntegerField': 'bigint',
            'IPAddressField': 'char(15)',
            'GenericIPAddressField': 'char(39)',
            'NullBooleanField': 'bool',
            'OneToOneField': 'integer',
            'PositiveIntegerField': 'integer UNSIGNED',
            'PositiveSmallIntegerField': 'smallint UNSIGNED',
            'SlugField': 'varchar(%(max_length)s)',
            'SmallIntegerField': 'smallint',
            'TextField': 'longtext',
            'TimeField': 'time',
            'UUIDField': 'char(32)',
        }

    ORM单表的增删改查

    配置连接数据库

    1. 创建库:create database db01

    2. 修改配置:在setting.py中更改如下内容

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'db01',
            'HOST':'127.0.0.1',
            'PORT':3306,
            'USER':'root',
            'PASSWORD':'123'
        }
    }

    3.在项目主目录下面的init文件中写上如下内容

    import pymysql
    pymysql.install_as_MySQLdb()

    注意:前提是需要安装pymysql : pip install pymysql

    4.在pycharm中连接mysql,可以使用pycharm自带的sql可视化工具

    在说增删改查之前,先介绍几个简单的查询接口

    all()  '''获取表中所有数据,结果为queryset类型'''
    ret = models.Book.objects.all()
    
    filter()  '''获取部分数据,结果为queryset类型'''
    ret = models.Book.objects.filter(title='西游记')
    
    get()  '''获取单条数据,结果是model对象'''
    ret = models.Book.objects.get(title='西游记')
    '''关于get需要注意的点'''
    # 1. get() 获取有且只能有一条
    # 2.找不到会报错:Book matching query does not exist.
    # 3.结果超过1条也报错: get() returned more than one Book -- it returned 3!

    单表操作:增

    '''方式1'''
        obj = models.Book( # obj就是一个普通的类对象
            title='西游记',
            price=2.8,
            # pub_date='2000-08-12',  # 可以直接写固定时间,也可以写datetime当前时间
            pub_date=datetime.datetime.now(),  #时间日期类型
            publish='人民出版社',
        )
        obj.save() # 注意:必须要写save选项
    '''方式2'''
       obj = models.Book.objects.create(  # obj是当前创建的新的记录对象
            title='红楼梦',
            price=9.9,
            # pub_date='2000-08-12',  #这样的格式字符串
            pub_date=datetime.datetime.now(),  # 时间日期类型
            publish='人民出版社',
        )
        
    '''批量添加'''
        obj_list = [] # 创建一个空列表,用来存放类对象
        for i in range(1,4): # 创建4个类对象,每个对象都有4个字段
            obj = models.Book(
                title='水浒传' + str(i),
                price=i,
                pub_date=f'2000-08-1{i}',
                publish='夕阳红出版社',
            )
            obj_list.append(obj) # 将类对象添加到列表中
        models.Book.objects.bulk_create(obj_list) # 批量添加

    单表操作:删

    '''query类型数据和模型类对象都可以调用delete方法来进行删除'''
    models.Book.objects.filter(title='西游记').delete()
    models.Book.objects.get(id=3).delete() 

    单表操作:改

    '''方式1'''
    models.Book.objects.filter(id=4).update(
         title='西游记',
         price=4,
     )
    '''方式2'''
    obj = models.Book.objects.get(id=6)
    obj.price = 18 # 找到model对象,使用model对象.属性修改值
    obj.save()
    
    obj.update()  # 注意:模型类对象不能直接使用update方法

    单表查询:查

    13个必知必会的查询接口

    前面已经提到了3个简单的查询接口,加上它们,一共有13个查询接口

    all()  '''获取表中所有数据,结果为queryset类型'''
    ret = models.Book.objects.all()
    
    filter()
    '''获取部分数据,结果为queryset类型''' ret = models.Book.objects.filter(title='西游记') ret = models.Book.objects.filter(id=1,title='三国演义') # 多条件查询,条件之间是且的关系(and)

    get() '''获取单条数据,结果是model对象''' ret = models.Book.objects.get(title='西游记') '''关于get需要注意的点''' # 1. get() 获取有且只能有一条 # 2.找不到会报错:Book matching query does not exist. # 3.结果超过1条也报错: get() returned more than one Book -- it returned 3! exclude(**kwargs): '''排除的意思,它包含了与所给筛选条件不匹配的对象,返回值是queryset类型''' models.Book.objects.exclude(id=6),# 返回id不等于6的所有的对象, models.Book.objects.all().exclude(id=6) # 在queryset基础上也调用exclude

                     order_by(*field): '''queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型''' models.Book.objects.all().order_by('price','id') '''注意点''' # 1.直接写price,默认是按照price升序排列, # 2.按照字段降序排列,就写个负号就行了:order_by('-price'), # 3.order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
    reverse()
    '''queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型,在排序基础上才能使用''' models.Book.objects.all().order_by('id').reverse() # 注意:要在order_by 基础上使用
    count():
    '''queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量''' models.Book.objects.all().count()
    first():
    '''queryset类型的数据来调用,返回第一条记录''' Book.objects.all()[0] = Book.objects.all().first() # 得到的都是model对象,不是queryset
    last():
    '''queryset类型的数据来调用,返回最后一条记录''' # 注意:在ORM中不能使用复数索引 ret = models.Book.objects.all()[-1] # 报错,不支持负数索引:Negative indexing is not supported.

    exists(): '''queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False'''
    values(
    *field): '''用的比较多,queryset类型的数据来调用,返回一个QuerySet''' ret = models.Book.objects.values('title','price') # 获取所有记录的某些字段数据,结果为querset类型,里面的元素是字典类型数据,属性名称为键,对应记录的字段数据为值 '''还可以通过queryset类型数据来调用''' ret = models.Book.objects.all().values('title','price')
    values_list(
    *field): '''它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列''' ret = models.Book.objects.all().values_list('title','price') ret = models.Book.objects.values_list('title','price')
    distinct():
    '''values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复记录''' ret = models.Book.objects.all().values_list('price').distinct()

    filter基于双下划线的模糊查询

    # 1.按日期查询
    ret = models.Book.objects.filter(pub_date__year='2000', pub_date__month='8',pub_date__day='12')
    
    
    # 2.以..开头/结尾   
    ret = models.Book.objects.filter(title__startswith='少妇') # 以..开头(区分大小写)
    ret = models.Book.objects.filter(title__istartswith='py') # 以..开头(不区分大小写)
    ret = models.Book.objects.filter(title__endswith='2') # 以..结尾(区分大小写)
    
    
    # 3.包含
    ret = models.Book.objects.filter(title_icontains='python') # title值中包含python的(区分大小写)
    ret = models.Book.objects.filter(title__icontains='python')  # title值中包含python的(不区分大小写)
    
    
    # 4.数字等于.../数字在某个范围内
    ret = models.Book.objects.filter(price__in=[3,4])  # 等于3或者等于4 -- 3 or4
    ret = models.Book.objects.filter(price__range=[1,3]) # 在1-3之间 between 1 and 3
    
    
    # 5.年份写纯数字和字符串数字都可以
    ret = models.Book.objects.filter(pub_date__year=2018)
    ret = models.Book.objects.filter(pub_date__year='2018')    
        
        
    # 6.大于/大于等于/小于/小于等于
    ret = models.Book.objects.filter(price__gt=3) # 价格大于3的
    ret = models.Book.objects.filter(price__gte=3) # 价格大于等于3的
    ret = models.Book.objects.filter(price__lt=3) # 价格小于3的
    ret = models.Book.objects.filter(price__lte=3) # 价格小于等于3的

    ORM多表关系的增删改查

    ORM多表关系的创建

    from django.db import models
    
    
    # 作者表
    class Author(models.Model): # 比较常用的信息放到这个表里面
        name=models.CharField( max_length=32)
        age=models.IntegerField()  #int
        # 与AuthorDetail建立一对一的关系,一对一的这个关系字段写在两个表的任意一个表里面都可以
        ad = models.OneToOneField(to="AuthorDetail", to_field='id', on_delete=models.CASCADE)
    
    # 作者详细信息表
    class AuthorDetail(models.Model): # 不常用的放到这个表里面
        birthday=models.DateField()
        telephone=models.CharField(max_length=11)
        addr=models.CharField(max_length=64)
    
    
    # 出版社表
    class Publish(models.Model):
        name=models.CharField( max_length=32)
        city=models.CharField( max_length=32)
    
    
    # 书籍表
    class Book(models.Model):
        title = models.CharField( max_length=32)
        publishDate=models.DateField()
        price=models.DecimalField(max_digits=5,decimal_places=2)
        # publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE)
        publish=models.ForeignKey(to="Publish") #默认级联删除,默认关联的是另外一张表的id字段
        authors=models.ManyToManyField(to='Author',) #自动创建第三张表,id author_id book_id,不会作为本表的字段出现

    创建字段的一些参数讲解

    # 1.null  
    '''如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.'''
     
        
    # 2.blank
    '''
    如果为True,该字段允许不填。默认为False。
    要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
    如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
    '''
    
    
    # 3.default
    '''
    字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
    '''
    
    
    # 4.primary_key
    '''
    如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
    Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
    否则没必要设置任何一个字段的primary_key=True。
    '''
    
    # 5.unique
    '''如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的'''
    
    
    # 6.choices
    '''由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。'''
    
    
    # 7.db_index
    '''如果db_index=True 则代表着为此字段设置数据库索引'''
    
    
    # DatetimeField、DateField、TimeField这个三个时间字段,都可以设置如下属性。
    
    # 8.auto_now_add
    '''配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库'''
    
    
    # 9.auto_now
    '''配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间'''

    Tip:关于choices属性额外的补充

    sex = models.IntegerField(choices=((1, '男性'), (2, '女性')))
    '''注意点'''
    # 1.数据库里面存的是1或者2
    # 2.通过model模型类对象.get_属性名称_display()可以获取到数字对应的文本内容

    Tip:关于auto_now_add和auto_now属性额外的补充

    class t1(models.Model):
        d1 = models.DateTimeField(auto_now_add=True,null=True)  #自动添加创建记录的时间
        d2 = models.DateTimeField(auto_now=True,null=True) #自动添加创建记录的时间,更新记录是也能自动更新为最新时间
    '''注意点'''
    # 1.auto_now 自动更新时间只有在save更新时才生效,update不生效
    # 2.所以如果要做更新时间的处理,那么最好手动获取当前时间并修改
        

    多表操作:增

    # 一对一
        # 1.用create增
        models.AuthorDetail.objects.create(
            birthday='2018-01-01',
            telephone='13800000000',
            addr='北京'
        )
        ad_obj = models.AuthorDetail.objects.get(id=1) # 创建一对一的关联model对象
        models.Author.objects.create(
            name='张三',
            age=38,
            # ad=ad_obj, # 方法一:写关联对象
            ad_id=2, # 方法二:直接写关联id值
        )
        # 2.用类对象去增
        ad_obj = models.AuthorDetail.objects.get(id=4)
        obj= models.Author(
            name='杨浩',
            age=47,
            ad=ad_obj, # 方法一
            # ad_id=3, #  方法二
        )
        obj.save()
    
    # 一对多
    '''出版社和书是一对多的关系;一个出版社可以出版多本书'''
    # 一对多,在多的一方写关联语句
        models.Book.objects.create(
            title='西游记',
            publishDate='2018-08-08',
            price=22,
            # publishs=models.Publish.objects.get(id=1), # 方法一
            publishs_id=1, # 方法二
        )
    
     # 多对多
    '''书和作者是多对多的关系;一本书可以有多个作者,一个作者也可以写很多本书'''
        obj = models.Book.objects.filter(id=1).first()
        # 方法一:通过get(id=?)获取对象
        a1 = models.Author.objects.get(id=1)
        a2 = models.Author.objects.get(id=2)
        obj.authors.add(a1,a2)
        # 方法二:add中直接写id
        obj.authors.add(1,2)
        # 方法三:id写入列表中,用*号打散
        obj.authors.add(*[1,2])

    多表操作:删

    # 一对一和一对多删除
        '''一对一和一对多 ,基本和单表一样(级联删除)'''
        models.Author.objects.get(id=1).delete()
        
        models.AuthorDetail.objects.get(id=2).delete()
        models.Book.objects.get(id=1).delete()
    
    # 多对多删除
        ret = models.Book.objects.get(id=2)
        ret.authors.clear()  # 清空该书籍对应的第三张表中的记录(全部删除)
        ret.authors.remove(3,4)  #指定删除该书和哪些作者的关系 (指定删除)
  • 相关阅读:
    【Android命令行】apktool参数详解
    【Android】ANR+OOM+FC
    如何创建低成本沙箱环境?推荐你使用API仿真!
    关于代码覆盖率,你不可不知的两大陷阱!
    如何借助自动创建单元测试来提高单元测试的投资回报率(ROI)?
    [实用指南]如何使您的旧代码库(遗留代码)符合MISRA C 2012编码规范?
    超实用的10个技巧!让您无论使用哪种静态分析工具都能轻松更新现有的静态分析实现
    主数据管理(MDM)的6大层级简述,你不可不知的数据治理参考!
    【收藏】关于元数据(Metadata)和元数据管理,这是我的见过最全的解读!
    机器学习 | 基于机器学习的供应链管理之销售库存优化分析(实操分享)
  • 原文地址:https://www.cnblogs.com/libolun/p/13688026.html
Copyright © 2011-2022 走看看