模型2

模型

一、数据库概述与配置

1、ORM

  • 概述
    中文为对象关系映射
    Django提供了各种数据库的支持 为大多数数据库提供了统一的接口 以方便请求大多数数据库
  • 作用
    通过ORM可以使用类的方式进行操作数据库 而不用再写原生SQL
  • 任务
    根据对象的类型生成表结构
    将对象的操作转换为SQL语句
  • 优点
    易用性:使用ORM做数据库的开发 可以有效的减少重复SQL的概率 写出来的模型也会更加直观清晰
    性能损耗小 : ORM进行底层转化会有一定开销 但是总体来看 好处大于消耗的
    设计灵活:可以写出复杂的查询
    可移植性:底层封装了对数据库的实现 支持多个关系的数据库引擎 所以可以非常轻松的更改数据库

2、数据库配置

  • 默认配置
    DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': BASE_DIR / 'db.sqlite3',
    }
    }
  • MySQL连接
    settings.py
    DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'day40django',
    'HOST': '127.0.0.1',
    'PORT': '3306',
    'USER': 'root',
    'PASSWORD': '123456',
    }
    }
    • 安装mysql扩展库
      pip install pymysql
    • project/init
      import pymysql
      pymysql.install_as_MySQLdb()

3、表分析

  • 需求
    创建用户表
  • 所需字段
    id 用户名 密码 性别 年龄 个人简介 头像 是否删除 注册时间

二、定义模型

1、字段类型

字段名称 字段说明 参数
AutoField 一个根据实际id进行自动增长的inter field(默认创建的) primary_key = True
CharField varchar类型字段 max_length 存储值最大长度
TextField longtext 长文本
IntegerField int类型字段 存储整形
SmallInterField 小整数 -32768-32767
DecimalField 存储浮点型 更加精准 max_digits=None 位数长度decimal_places=None 小数的位数
FloatField 浮点型
BooleanField 存储bool值 True/False
NullBooleanField 存储Null/True/False
DateField date字段 auto_now=False 如果对数据进行修改则会自动保存修改时间
auto_now_add=False 会自动添加第一次保存的时间 俩个不同同时设定
TimeField time字段 同上
DateTimeField datetimefield字段 同上
FileField 文件上传 upload_to = '' 文件上传保存的路径
ImageField 图片上传字段(继承了FileField 对图像进行了验证 确保是一个有效的图片) 同上

2、字段选项

通过字段选项 可以实现对字段约束 在字段对象使用关键字参数进行指定

选项 说明
null 如果设置为True 则当前字段可以为null
blank 如果设置为True 则当前字段可以什么值都没有 设置在字符串类型的字段上
db_column 设置字段名称 如果不设置 默认为属性名
db_index 设置为True 常规索引
unique 设置为True 唯一索引
primary_key 设置为True 主键索引
default 默认值

3、模型创建

models.py

from django.db import models

# Create your models here.
class User(models.Model):
    # 用户名
    username = models.CharField(max_length=12)
    # 密码
    userpass = models.CharField(max_length=64)
    # 性别
    sex = models.BooleanField(default=True)
    # 年龄
    age = models.SmallIntegerField(default=18)
    # 个人简介
    info = models.CharField(max_length=200, default='个人简介')
    # 头像
    icon = models.CharField(max_length=60, default='default.jpg')
    # 是否删除
    isDelete = models.BooleanField(default=False)
    # 注册时间
    registerTime = models.DateTimeField(auto_now_add=True)

4、迁移到数据库中

  • 生成迁移文件
    python manage.py makemigrations
  • 迁移到数据库中
    python manage.py migrate
  • 注意
    表名默认为 应用名_类名 全都小写
    app_user

5、关系

  • 一对一
  • 一对多
  • 多对多

6、元选项

  • 作用
    在模型类中使用Meta类设置一些信息
  • 实例
    class User(models.Model):
    ...
    registerTime = models.DateTimeField(auto_now_add=True)
    class Meta:
    db_table = 'user' # 更改表名称为user
    # ordering = ['-age', 'id'] # 按照年龄降序 如果年龄相同 id升序
    ordering = ['-age'] # 按照年龄降序

7、数据测试

  • 数据添加
    # 保存数据(数据添加)
    def save(req):
    u = User()
    u.username = 'lucky'
    u.userpass = '123456'
    u.sex = True
    u.age = 18
    u.info = 'lucky的个人简介'
    u.icon = './lucky.jpg'
    u.isDelete = False
    u.save()
    return HttpResponse('数据添加')

  • 数据查询
    # 查询数据
    def select(req):
    u = User.objects.all()
    print(u)
    for o in u:
    # print(o.username,'-------',o.userpass)
    print(o)
    return HttpResponse('数据查询')

  • 注意
    当打印每一个对象的时候 发现数据并不直观因为都是object 更改类 添加str方法 作为友好输出
    更改User模型类
    from django.db import models

    # Create your models here.
    class User(models.Model):
        # 用户名
        username = models.CharField(max_length=12)
        # 密码
        userpass = models.CharField(max_length=64)
        # 性别
        sex = models.BooleanField(default=True)
        # 年龄
        age = models.SmallIntegerField(default=18, db_column='u_age')
        # 个人简介
        info = models.CharField(max_length=200, default='个人简介')
        # 头像
        icon = models.CharField(max_length=60, default='default.jpg')
        # 是否删除
        isDelete = models.BooleanField(default=False)
        # 注册时间
        registerTime = models.DateTimeField(auto_now_add=True)
        def __str__(self):
            return self.username
        class Meta:
            db_table = 'user'  # 更改表名称为user
            # ordering = ['-age', 'id']
            ordering = ['-age']  # 按照年龄降序
    

8、objects

  • 概念

    • 是Manager类的对象 用于与数据库进行交互
    • 如果定义模型时没有指定objects 则会默认创建objects
  • 问题
    在查询的时候 好多地方都使用了同一个过滤器 可不可以 把过滤器放到objects中 对原始查询集进行过滤

  • 自定义管理器对象
    models.py
    from django.db import models

    # 继承模型管理器类
    class MyManager(models.Manager):
        # 重写查询方法
        def get_queryset(self):
            # 重写了父类中的get_queryset方法  并增加了过滤功能 过滤掉isdelete为True的数据
            return super().get_queryset().filter(isDelete=False)
            # return super().get_queryset()
    
    
    # Create your models here.
    class User(models.Model):
        # 自定义模型管理器对象
        objects = models.Manager()
        o = models.Manager()   # 可以有多个模型管理器
        my_obj = MyManager()  # 自定义添加过滤功能的模型管理器
        ...
        # 注册时间
        registerTime = models.DateTimeField(auto_now_add=True)
        def __str__(self):
            return self.username
        class Meta:
            db_table = 'user'  # 更改表名称为user
            # ordering = ['-age', 'id']
            # ordering = ['-age']  # 按照年龄降序
    

    views.py
    def select(req):
    # 使用自定义模型管理器
    # u = User.objects.all()
    # u = User.o.all()

        # 使用自定义模型管理器并重写了查询方法
        # u = User.my_obj.all()  # 等同于  u = User.objects.filter(isDelete=False)
        
        u = User.objects.filter(isDelete=False)
        print(u.query)
        for o in u:
            # print(o.username,'-------',o.userpass)
            print(o.isDelete)
        # u = User.objects
        # print(u)
        # print(type(u))
        return HttpResponse('数据查询')
    

三、数据添加

1、创建对象

  • 概述
    当创建对象以后 使用属性进行赋值 当调用save以后 才与数据库进行交互
  • 实例
    def save(req):
    u = User()
    u.username = 'lucky'
    u.userpass = '123456'
    u.sex = True
    u.age = 18
    u.info = 'lucky的个人简介'
    u.icon = './lucky.jpg'
    u.isDelete = False
    u.save()
    return HttpResponse('数据添加')

2、实例化对象并传参

  • 概述
    当模型类实例化以后 进行参数传递
  • 实例
    #数据添加第二种方法
    u = User(3, '张三','123456')
    u = User(username='李四', userpass='123456')
    u.save()
    return HttpResponse('数据添加')
  • 注意
    如果不指定参数 id也需要传参

3、create方法

  • 使用create方法
    # 第三种数据添加方法
    User.objects.create(username='王五', userpass='123456')
    return HttpResponse('数据添加')

  • 重写create方法
    models.py
    class MyManager(models.Manager):
    def get_queryset(self):
    # 重写了父类中的get_queryset方法 并增加了过滤功能 过滤掉isdelete为True的数据
    return super().get_queryset().filter(isDelete=False)
    # return super().get_queryset()

        # 重写create方法
        def create(self, username='', userpass='', sex=True,age=18,info='lucky的个人简介', icon='./lucky.jpg', isDelete=False):
            u = self.model()
            u.username = username
            u.userpass = userpass
            u.sex = sex
            u.age = age
            u.info = info
            u.icon = icon
            u.isDelete = isDelete
            return u
    
    
    # Create your models here.
    class User(models.Model):
        # 自定义模型管理器对象
        objects = models.Manager()
        # o = models.Manager()
        my_obj = MyManager()
        # 用户名
        ...
    

    views.py
    u = User.my_obj.create('赵六', '123456')
    u.save()

4、添加多条数据 bulk_create()

  • 概述
    批量添加数据
    u1 = User(username='秦七', userpass='123456')
    u2 = User(username='王老八', userpass='123456')
    User.objects.bulk_create([u1, u2])

5、类方法

  • 概述
    通过classmethod方法进行数据添加
  • 实例
    models.py
    # Create your models here.
    class User(models.Model):
    # 自定义模型管理器对象
    objects = models.Manager()
    # o = models.Manager()
    my_obj = MyManager()
    ...
    # 类方法用于添加数据
    @classmethod
    def create(cls, username='', userpass='', sex=True,age=18,info='lucky的个人简介', icon='./lucky.jpg', isDelete=False):
    return cls(username=username, userpass=userpass, sex=sex,age=age,info=info, icon=icon, isDelete=isDelete)
    views.py
    # 第五种 使用类方法
    User.create('婷婷', '123456').save()
    return HttpResponse('数据添加')

四、查询

1、数据查询名词解析

  • 查询集
    从数据库中获取数据查询的集合
  • 原始查询集
    调用get_queryset() 方法查询获取到的数据为原始查询集 不作为数据的提取
  • 数据查询集
    通过原始查询集配合过滤器等最终得到的数据
  • 过滤器
    对数据进行筛选

2、返回查询集的过滤器

  • all()
    概述: 返回所有
    def show(req):
    u = User.objects.all()
    print(u)
    return render(req, 'show.html', {'data': u})
  • filter()
    过滤掉不符合条件的数据
    # 查询没有删除的数据和性别为False的数据
    u = User.objects.filter(isDelete=False).filter(sex=False)
    u = User.objects.filter(isDelete=False, sex=False)
  • exclude()
    过滤掉符合条件的数据
    # 过滤掉没有删除的数据和性别为False的数据
    u = User.objects.exclude(isDelete=False, sex=False)
  • order_by()
    排序
    • '字段' 升序
    • '-字段' 降序
      u = User.objects.order_by('-age')
      u = User.objects.order_by('age' ,'-id')
  • values()
    返回一个列表 每条数据是一个字典
    • values() 返回所有
    • values(field1,[field2....]) 返回指定字段的值
      u = User.objects.values()
      u = User.objects.values('username')
  • extra()
    起别名
    extra(select={'new': 'old'})
    u = User.objects.all().extra(select={'name': 'username'})
    print(u[0].name)

3、返回单个值的过滤器

  • get()
    返回单个满足条件的对象
    u = User.objects.get(age=20)
    u = User.objects.get(age=18)
    u = User.objects.get(age=180)
    注意: 只能返回一个值 如果大于小于一个值 都会抛出异常
  • count()
    放回当前查询集的数据条数
    u = User.objects.all().count()
    u = User.objects.filter(age=18).count()
  • first()
    返回查询集中的第一个对象
    u = User.objects.order_by('-age').first()
  • last()
    最后一个对象
    u = User.objects.order_by('-age').last()
  • exists()
    判断筛选后的数据是否存在
    u = User.objects.filter(age=18).exists()
    u = User.objects.filter(age=180).exists()
  • values_list()
    将模型对象转换成列表 达到减少内存损耗 提高性能
    u = User.objects.values_list()

4、字段查询

  • 概述
    实现where子句 filter、exclude等参数
  • 语法
    属性名__比较运算符=值
  • 更改表结构 查询区分大小写
    alter table user modify username varchar(20) collate utf8_bin not null;
    alter table user modify username varchar(20) character set utf8 not null;
  • exact()
    表示判等 不区分大小写
    u = User.objects.filter(username__exact='lucky')
    u = User.objects.filter(username='lucky')
  • contains
    包含 (区分大小写)
    u = User.objects.filter(username__contains='l')
    u = User.objects.filter(username__contains='L')
    不区分大小写
    u = User.objects.filter(username__icontains='l')
  • startswith
    以...开头 (区分大小写)
    u = User.objects.filter(username__startswith='L')
    不区分大小写
    u = User.objects.filter(username__istartswith='L')
  • endswith
    以...结尾 (区分大小写)
    u = User.objects.filter(username__endswith='Y')
    不区分大小写
    u = User.objects.filter(username__iendswith='Y')
  • null
    查询数据为null
    # 查询为null的数据
    u = User.objects.filter(username__isnull=True)
    u = User.objects.filter(username=None)
    # 查询不为空的数据
    u = User.objects.filter(username__isnull=False)
    u = User.objects.exclude(username__isnull=True)
  • in
    是否包含范围内
    # 包含范围内
    u = User.objects.filter(id__in=[1,2,3,4,5])
    u = User.objects.filter(pk__in=[1,2,3,4,5])
    # 不包含范围内
    u = User.objects.exclude(pk__in=[1,2,3,4,5])
  • 比较运算符
    • gt 大于
    • gte 大于等于
    • lt 小于
    • lte 小于等于
      u = User.objects.filter(id__gt=10)
      u = User.objects.filter(id__gte=10)
      u = User.objects.filter(id__lt=10)
      u = User.objects.filter(id__lte=10)

5、聚合函数

  • 导入
    from django.db.models import Avg,Max,Min,Sum,Count
  • 方法
    aggregate()
  • 实例
    u = User.objects.aggregate(Avg('age'))
    u = User.objects.aggregate(Max('age'))
    u = User.objects.aggregate(Min('age'))
    u = User.objects.aggregate(Sum('age'))
    u = User.objects.aggregate(Count('age'))

6、限制结果数量all()

  • 和列表截取一样的操作

    u = User.objects.all()
    print(u[0])
    print(u[100])
    print(u[0:10])
    print(u[0:10:2])

五、修改与删除

1、修改

  • save()
    def update(req):
    # 获取要修改数据的对象
    u1 = User.objects.get(pk=1)
    print(u1)
    u1.sex = False
    u1.age = 17
    u1.save()
    return HttpResponse('update')
  • update() 值的修改
    # 修改多个
    u = User.objects.filter(id__in=[1,2,3])
    # print(u)
    u.update(age=17, sex=False)
  • 区别
    save适用于修改单个对象
    update适用于修改多个对象

2、删除

  • delete
    u = User.objects.filter(id__in=[1,2,3])
    u.delete()

六、高级查询

1、Q对象

  • 导入
    from django.db.models import Q
  • 作用
    逻辑或
    # 逻辑或
    u = User.objects.filter(Q(age=18)|Q(sex=True))
    # 逻辑与
    u = User.objects.filter(age=18, sex=True)
    u = User.objects.filter(age=18).filter(sex=True)
  • 逻辑非
    u = User.objects.filter(~Q(age=18))
    u = User.objects.exclude(Q(age=18))

2、F对象

  • 导入
    from django.db.models import F
  • 概述
    模型类中A与B字段之间的比较
    # 比较俩个字段相等的值
    u = User.objects.filter(id=F('age'))
    # 比较id大于age字段的值
    u = User.objects.filter(id__gt=F('age'))

3、原生SQL操作

  • 格式
    类名.objects.raw(sql)
  • 实例
    u = User.objects.raw('select * from user')
    u = User.objects.raw('select id, u_age, sex from user')
  • 注意
    查询某个字段时 包含主键

4、获取原生SQL

  • 格式
    对象.query
  • 示例
    u = User.objects.filter(id__gt=F('age'))
    print(u)
    print(u.query)

5、关联查询

  • 作用
    俩个表关联
  • 语法
    关联模型类名小写__属性名__ 比较运算符=值
  • 实例
    s = Grade.objects.filter(students__sname__contains='lucky')

七、模型对应关系

1、概述

  • 主从表
    没有声明关系的表为主表
    声明关系的表为从表
  • 对应关系
    • 一对一
    • 一对多
    • 多对多

2、一对一模型关系 OneToOneField

  • 说明
    使用OneToOneField声明模型关系为一对一关系将OneToOneField放与从表中

  • 使用场景
    表的字段太多 进行拆分

  • 关系位置
    哪张表都可以

  • 创建模型类
    用户模型类
    from django.db import models

    # Create your models here.
    class User(models.Model):
        # 用户名
        username = models.CharField(max_length=12)
        # 密码
        userpass = models.CharField(max_length=64)
        # 性别
        sex = models.BooleanField(default=True)
        # 年龄
        age = models.SmallIntegerField(default=18, db_column='u_age')
        # 个人简介
        info = models.CharField(max_length=200, default='个人简介')
        # 头像
        icon = models.CharField(max_length=60, default='default.jpg')
        # 是否删除
        isDelete = models.BooleanField(default=False)
        # 注册时间
        registerTime = models.DateTimeField(auto_now_add=True)
    
        # 类方法用于添加数据
        def __str__(self):
            return self.username
        class Meta:
            db_table = 'user'  # 更改表名称为user
    

    身份证模型类
    # 身份证
    class IdCard(models.Model):
    # 身份证号码
    num = models.CharField(max_length=18)
    name = models.CharField(max_length=10)
    sex = models.BooleanField(default=True)
    birth = models.DateTimeField(auto_now_add=True)
    address = models.CharField(max_length=50, default='地址')
    # 创建了模型一对第一的关系 从表随着主表的删除而删除
    # user = models.OneToOneField(User, on_delete=models.CASCADE)
    # 受保护 模式 如果从表有关联数据 则不能删除主表关联的数据
    # user = models.OneToOneField(User, on_delete=models.PROTECT)
    # 置空模式 设置为null
    user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
    def str(self):
    return self.name
    class Meta:
    db_table = 'idcard' # 更改表名称为user

  • 添加一对一模型数据
    添加主表
    def addUser(req):
    User(username='张三').save()
    User(username='李四').save()
    User(username='王五').save()
    return HttpResponse('一对一模型关系添加User数据')
    添加从表
    def addIdCard(req):
    import random
    u = User.objects.first()
    IdCard(num=random.randrange(100000000,99999999999), name=u.username,user=u).save()
    return HttpResponse('一对一模型关系添加IdCard数据')

  • 查询
    通过主表查从表
    主表对象.从表类名小写
    u = User.objects.first()
    # print(u)
    print(u.idcard)
    print(u.idcard.num)
    通过从表查主表
    从表对象.外键属性名
    idcard = IdCard.objects.first()
    # print(idcard)
    print(idcard.user)
    print(idcard.user.sex)

posted @ 2022-03-01 09:49  寻月隐君  阅读(20)  评论(0编辑  收藏  举报