zoukankan      html  css  js  c++  java
  • django—数据库

    一、使用传统pymysql执行与sqlite区别

    ①使用pymysql执行原生sql语句来操作数据
    1.sql语句比较复杂,且不好管理
    2.sql语句安全性无法保持
    3.数据库创建、数据表生成、数据添加以及数据迁移等非常麻烦
    4.sql语句性能不够好

    ②使用ORM框架创建数据库
    mysql中的对象
    1.数据库
    需要手动创建数据库

    2.数据表
    a.与ORM中的模型类一一对应
    b.在子应用的models.py中定义模型类

    3.字段
    a.与模型类的类属性一一对应

    4.记录
    a.与模型类对象一一对应

    二、在django中创建数据库

    1、settings.py中

    # Database
    # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
    # 指定数据库的配置信息
    DATABASES = {
        # 使用的默认数据库信息
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            # a.指定使用的数据库引擎(使用哪种类型数据库?)
            # 'ENGINE': 'django.db.backends.mysql',
            # b.指定数据库名称
            'NAME': BASE_DIR / 'db.sqlite3',
            # 'NAME': 'my_django',
            # c.指定数据库的用户名
            # 'USER': 'root',
            # d.指定数据库的密码
            # 'PASSWORD': '123456',
            # e.指定数据库主机地址
            # 'HOST': 'localhost',
            # f.指定数据库的端口号
            # 'PORT': 3306
        }
    }

    2. models.py中

    a.定义模型类必须继承Model或者Model子类,一个模型类相当于一个table
    b.定义的类属性(Field对象)为表中的字段信息
    c.默认表名为子应用名_模型类名小写
    d.默认会自动创建一个id主键(自增、非空)
    e.生成迁移脚本:python manage.py makemigrations 子应用名
    f.生成的迁移脚本会自动放置到子应用的migrations目录中
    g.执行迁移脚本:python manage.py migrate 子应用名

    from django.db import models
    
    # Create your models here.
    
    
    class People(models.Model):
    
        name = models.CharField(max_length=20)
        age = models.IntegerField()

    生成迁移脚本:python manage.py makemigrations 子应用名,生成migrations文件夹,里面是迁移脚本

     执行迁移脚本:python manage.py migrate 子应用名

    执行后可看到生成的DB,如果没有sqlite驱动,按提示下载

     

    from django.db import models
    
    
    class People(models.Model):
        """
        a.定义模型类必须继承Model或者Model子类,一个模型类相当于一个table
        b.定义的类属性(Field对象)为表中的字段信息
        c.默认表名为子应用名_模型类名小写
        d.默认会自动创建一个id主键(自增、非空)
        e.生成迁移脚本:python manage.py makemigrations 子应用名
        f.生成的迁移脚本会自动放置到子应用的migrations目录中
        g.执行迁移脚本:python manage.py migrate 子应用名
        """
        name1 = models.CharField(max_length=20)
        age = models.IntegerField()
    
    
    class Projects(models.Model):
    
        # 一个数据库模型类中只允许定义一个设置了primary_key=True的字段
        # 一旦某个字段设置了primary_key=True,那么ORM框架就不会自动创建id主键
        # num = models.IntegerField(primary_key=True)
        id = models.AutoField(primary_key=True, verbose_name='id主键', help_text='id主键')
    
        # a.CharField指定varchar类型
        # b.CharField必须得设置max_length参数,指定最大长度
        # c.verbose_name与help_text指定中文的描述,在admin后台站点以及在接口文档平台中会使用到
        # d.unique=True设置唯一约束,默认unique=False
        name = models.CharField(verbose_name='项目名称', help_text='项目名称', max_length=20,
                                unique=True)
        leader = models.CharField(verbose_name='项目负责人', help_text='项目负责人', max_length=10)
    
        # e.default指定当前字段的默认值
        is_execute = models.BooleanField(verbose_name='是否开展', help_text='是否开展', default=True)
        # f.null指定当前字段是否允许保持null空值
        # g.blank指定前端在创建数据时是否允许不输入
        desc = models.TextField(verbose_name='项目描述信息', help_text='项目描述信息',
                                null=True, blank=True, default='')
    
        # DateTimeField指定日期时间类型
        # a.auto_now_add=True,在创建一条数据时,会自动将当前时间赋值给create_time,只修改一次
        # b.auto_now=True,每次在更新数据时,会自动将当前时间赋值给update_time,只要修改就会自动更新
        create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', help_text='创建时间')
        update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间', help_text='更新时间')
    
        class Meta:
            # a.可以在Meta内部类中修改当前表的元数据信息
            # b.指定创建的数据表名称
            db_table = 'tb_projects'
            # c.指定创建的数据表中文描述信息
            verbose_name = '项目表'
            verbose_name_plural = '项目表'
    
        def __str__(self):
            return self.name
    from django.db import models
    
    
    # 表与表之间有哪些关联关系?
    # Projects与Interfaces表,一对多的关系
    # 学生表与学生详细信息表,一对一的关系
    # 学生表与课程表,多对多的关系
    
    # 一条项目数据:id为1的测试开发平台项目
    # 多条接口数据:id为1的登录接口、id为2的注册接口、id为3的生成用例的接口
    class Interfaces(models.Model):
        id = models.AutoField(primary_key=True, verbose_name='id主键', help_text='id主键')
        name = models.CharField(verbose_name='接口名称', help_text='接口名称', max_length=15, unique=True)
        tester = models.CharField(verbose_name='测试人员', help_text='测试人员', max_length=10)
        # a.可以使用ForeignKey在从表中指定外键字段,在一对多关系中‘多’的那侧添加外键字段
        # b.ForeignKey第一个参数,需要指定关联的父表,往往使用'子应用名.父表模型类名'
        # c.必须指定on_delete级联删除策略
        # d.级联删除策略有如下种类:
        # CASCADE:当父表数据删除之后,对应的从表数据会被自动删除
        # SET_NULL:当父表数据删除之后,对应的从表数据的外键字段会被自动设置为null
        # PROTECT:当父表数据删除时,如果存在对应的从表数据,那么会抛出异常
        # SET_DEFAULT:父表数据删除之后,对应的从表数据的外键字段会被自动设置为default参数指定的值
        # 创建创建数据表时,会自动创建projects_id作为字段名,用于存放父表外键值
        # ForeignKey: 一对多
        # OneToOneField:一对一
        # ManyToManyField:多对多
        projects = models.ForeignKey('projects.Projects', on_delete=models.CASCADE)
        create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', help_text='创建时间')
        update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间', help_text='更新时间')
    
        class Meta:
            db_table = 'tb_interfaces'
            verbose_name = '接口表'
            verbose_name_plural = '接口表'
    
        def __str__(self):
            return self.name

     

    添加数据

    一、创建(C)
    方式一:
    a.直接使用模型类来创建模型对象
    b.必须调用save()方法才会执行sql语句(提交)
    one_project = Projects(name='XXX金融项目11', leader='大脑斧', desc='这是一个描述')
    one_project.save()

    方式二:
    a.可以使用模型类.objects为manager对象
    b.可以使用manager对象.create方法(关键字参数)
    c.无需调用save方法,会自动提交
    one_project = Projects.objects.create(name='XXX在线商城项目11', leader='开始', desc='xxx描述')

    添加子表数据
    Interfaces(name='登录接口', tester='Aaron', projects_id=one_project.id)
    one_interface = Interfaces(name='登录接口', tester='Aaron', projects=one_project)
    one_interface = Interfaces.objects.create(name='登录接口', tester='Aaron', projects=one_project)

    二、更新数据(U)
    方式一:
    a.所有的模型类,会有一个默认的objects属性,是一个manager对象
    b.获取需要修改的模型类对象之后,重写相应的字段
    c.必须得调用save()方法,才会提交
    one_project = Projects.objects.get(id=5)
    one_project.name = 'XXX在线商城项目22'
    one_project.save()

    方式二:
    a.先将待修改的数据取出(查询集对象)
    b.然后调用update()方法
    c.无需调用save()方法,会自动提交
    qs = Projects.objects.filter(id=5).update(leader='唯一')

    三、查询(R)
    1.读取多条数据
    a.使用模型类.objects.all()
    b.返回QuerySet对象,类似于列表,但不是列表
    c.QuerySet对象,惰性查找,只有需要用到数据(len、取值、for)时,才会执行sql语句
    d.QuerySet对象中为模型类对象(数据)
    project_qs = Projects.objects.all()
    for pro in project_qs:
    print(pro.name)
    print(list(project_qs))

    2.读取一条数据
    方式一:
    a.可以使用模型类.objects.get()
    b.如果查询的结果为空,那么会抛出异常
    c.如果查询的结果超过一条数据,也会抛出异常
    d.get方法,往往会使用主键或者唯一键作为查询条件
    e.返回模型类对象(数据)
    one_project = Projects.objects.get(id=1)
    pk为django模型类内置的一个属性,是主键的别名
    one_project = Projects.objects.get(pk=1)
    one_project = Projects.objects.get(Projects.objects.get(leader='大脑斧'))

    方式二:
    a.模型类.objects.filter方法
    b.返回QuerySet对象
    c.如果查询的结果为空,那么会返回空的QuerySet对象
    d.如果查询的结果超过一条,也会返回多条结果所在的QuerySet对象
    e.字段名__查询类型=具体值
    f.查询类型种类?
    gt >
    gte >=
    lt <
    lte <=
    in 对处于列表中的值进行过滤
    contains 包含
    icontains 包含,忽略大小写
    startswith 以xxx开头
    istartswith 以xxx开头,忽略大小写
    endswith 以xxx结尾
    iendswith 以xxx结尾,忽略大小写
    isnull 是否为空

    qs = Projects.objects.filter(id=4)
    qs = Projects.objects.filter(pk=4)
    qs = Projects.objects.filter(id__exact=4)
    qs = Projects.objects.filter(id__in=[1, 3])
    qs = Projects.objects.filter(name__contains='金融')
    qs = Projects.objects.filter(update_time__gt='2021-01-18')

    exclude与filter为反向关系
    qs = Projects.objects.filter(id__gt=3)
    qs = Projects.objects.exclude(id__lte=3)

    取出某个项目所属接口名称中包含'登录'的项目
    关联查询
    关联模型类名小写__关联模型类中的字段名__查询类型=具体值
    关联模型类名1小写__关联模型类1中的外键名__关系模型类2中的字段名__查询类型=具体值
    qs = Projects.objects.filter(interfaces__name__contains='登录')
    qs = Interfaces.objects.filter(name__contains='登录')
    使用外键字段,可以取出父表中对应的模型类对象
    one_project = qs[0].projects
    return HttpResponse(one_project)


    QuerySet查询集的特性
    1、惰性查询
    2、链式调用
    a.查询集对象可以多次调用filter方法,进行过滤
    b.多个filter中的过滤条件为与的关系
    c.在一个filter方法中,可以写多个条件,每个条件之间以“逗号”分割,每个条件为与的关系

    3、哪些操作会让查询集执行sql语句? 查询集支持哪些操作?
    a.通过数字索引取值,但不支持负值索引
    b.支持切片操作
    c.支持.first()方法,可以取出查询集中的第一个元素,为模型类对象
    d.支持.last()方法,可以取出查询集中的最后一个元素,为模型类对象
    e.支持len(查询集对象),获取查询集的长度,也可以使用.count()方法
    f.支持.exists()方法,来判断查询集中是否有元素,如果有元素,那么返回True,否则返回False
    g.支持for循环迭代
    qs = Projects.objects.filter(name__contains='商城')

    逻辑关系
    a.与的关系
    one = qs.filter(leader='唯一')
    qs = Projects.objects.filter(name__contains='商城').filter(leader='唯一')
    qs = Projects.objects.filter(name__contains='商城', leader='唯一')

    b.或的关系
    可以使用Q对象来实现逻辑关系查询
    多个Q对象之间使用|,为或的关系
    多个Q对象之间使用&,为与的关系
    qs = Projects.objects.filter(Q(name__contains='商城') | Q(leader='大脑斧'))

    排序操作
    a.默认是以id主键升序来排序的
    b.查询集对象.order_by('字段名1','字段名2')
    c.默认指定的字段名为升序
    d.可以在字段名的前面添加-,代表以降序来排序

    删除操作(D)
    方式一:
    调用模型类对象中的delete()方法
    one_project = Projects.objects.get(pk=1)
    one_project.delete()

    方式二:
    使用查询集对象.delete(),可以将查询集中的所有数据删除
    one = Projects.objects.filter(name__contains='商城').delete()
    names = ['登录接口', '注册接口', '订单接口', '购物车接口']
    for i in range(20):
    random_str = ''.join(random.sample(string.ascii_letters + string.digits, 8))
    interface_name = random.choice(names) + random_str
    Interfaces.objects.create(name=interface_name, tester='Aaron', projects_id=random.choice([2, 3, 4, 5]))

    a.values和annotate为固定用法
    b.聚合运算需要设置为从表名小写
    c.使用外键id作为关联条件,同时会把外键id作为分组条件
    d.默认查询id和聚合运算的值
    e.聚合运算的别名会自动设置为从表名小写__聚合函数名小写
    f.可以给聚合运算设置关键词参数,会作为聚合运算的别名
    qs = Projects.objects.values('id').annotate(Count('interfaces'))
    qs = Projects.objects.values('id').annotate(interfaces=Count('interfaces'))
    qs = Projects.objects.annotate(interfaces=Count('interfaces'))
    return HttpResponse('')



    django中的objects.get和objects.filter方法的区别

  • 相关阅读:
    js怪招(摘录篇)
    猪八戒实习笔记(工具总结)
    2014年最新前端开发面试题(面霸题库)
    经典算法:快排的Javascript版本
    IE的CSS相关的BUG(整理一)
    setTimeout()的返回值
    面试回忆录(三)
    面试回忆录(二)
    读取指定文件夹下的全部文件,可通过正则进行过滤,返回文件路径数组 -- 基于node的一个函数
    Backbone简单示例
  • 原文地址:https://www.cnblogs.com/erchun/p/14289049.html
Copyright © 2011-2022 走看看