• Django中ORM介绍和字段及字段参数


    参考1

    参考2

    Django之Model操作

    1. Django项目如何使用ORM连接MySQL
        1. 手动创建数据库
        2. 在settings.py里面配置一下数据库的连接信息(告诉Django连接哪一个数据库)
            DATABASES = {
                'default': {
                    'ENGINE': 'django.db.backends.mysql',  # 连接数据库的类型
                    'NAME': 'day62xiawu',  # 数据库名字
                    'HOST': '127.0.0.1',  # IP
                    'PORT': 3306,  # 端口
                    'USER': 'root',  # 用户名
                    'PASSWORD': '123456',  # 密码
                }
            }
        3. 在和settings.py同目录下的__init__.py文件中,告诉Django用pymysql代替MySQLdb来连接数据库
            import pymysql
            pymysql.install_as_MySQLdb()
        4. 在app/models.py中,定义类,类一定要继承models.Model
            class Book(models.Model):
                id = models.AutoField(primary_key=True)
                title = models.CharField(max_length=32)
        5. 执行两条命令
            1. 在哪儿执行?
                在项目的根目录(有manage.py文件的那个目录)
            2. 命令
                python manage.py makemigrations   --> 将models.py文件中的改动记录在小本本(app/migrations/00xx_****.py)上
                
                python manage.py migrate           --> 将改动翻译成SQL语句,去数据库中执行
    2. 表和表之间的关系
        1. 一对多(出版社和书)
            publisher = models.ForeignKey(to="Publisher")
            
            在数据库中:
                有没有publisher这个字段?
                数据库中实际 生成的是一个 publisher_id 字段
            
        2. 多对多(作者和书)
            books = models.ManyToManyField(to="Book")
            
            在数据库中:
                是通过第三张表建立的关系
    
    3. 增删改查操作
        1. 单表增删改查
            增:
                models.Publisher.objects.create(name="沙河出版社")
            查:
                models.Publisher.objects.get(id=1)
                models.Publisher.objects.get(name="沙河出版社")
            删:
                models.Publisher.objects.get(id=1).delete()
            改:
                obj = models.Publisher.objects.get(id=1)
                obj.name = "沙河第二出版社"
                obj.save()
        2. 外键的增删改查
            增、删、查同上
            
            book_obj = models.Book.objects.get(id=1)
            
            book_obj.publisher 是什么?    *****
                和我这本书关联的出版社对象
                
                book_obj.publisher.id    和我这本书关联的出版社的id值
                book_obj.publisher.name  和我这本书关联的出版社的名称
                
            book_obj.publisher_id 是什么?
                和我这本书关联的出版社的id值
                
        3. 多对多操作
            
            1. 查id为1的作者都写过的书?
                author_obj = models.Author.objects.get(id=1)
                author_obj.books.all()     --> 和我这个作者关联的所有书对象
            2. 想给作者绑定多本书?
                author_obj = models.Author.objects.get(id=1)
                author_obj.books.set([1,2,3]) --> 把id是1、2、3的书和我这个作者关联上
    ORM概要

    一、ORM概念

    对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。

    简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。

    ORM在业务逻辑层和数据库层之间充当了桥梁的作用。 

    二、Django ORM 常用字段和参数 

    1、常用字段

    AutoField
    int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
    
    IntegerField
    一个整数类型,范围在 -2147483648 to 2147483647CharField
    字符类型,必须提供max_length参数, max_length表示字符长度。
    
    DateField
    日期字段,日期格式  YYYY-MM-DD,相当于Python中的datetime.date()实例。
    
    DateTimeField
    日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。

    AutoField(Field)
            - int自增列,必须填入参数 primary_key=True
    
        BigAutoField(AutoField)
            - bigint自增列,必须填入参数 primary_key=True
    
            注:当model中如果没有自增列,则自动会创建一个列名为id的列
            from django.db import models
    
            class UserInfo(models.Model):
                # 自动创建一个列名为id的且为自增的整数列
                username = models.CharField(max_length=32)
    
            class Group(models.Model):
                # 自定义自增列
                nid = models.AutoField(primary_key=True)
                name = models.CharField(max_length=32)
    
        SmallIntegerField(IntegerField):
            - 小整数 -32768 ~ 32767
    
        PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
            - 正小整数 0 ~ 32767
        IntegerField(Field)
            - 整数列(有符号的) -2147483648 ~ 2147483647
    
        PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
            - 正整数 0 ~ 2147483647
    
        BigIntegerField(IntegerField):
            - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
    
        BooleanField(Field)
            - 布尔值类型
    
        NullBooleanField(Field):
            - 可以为空的布尔值
    
        CharField(Field)
            - 字符类型
            - 必须提供max_length参数, max_length表示字符长度
    
        TextField(Field)
            - 文本类型
    
        EmailField(CharField):
            - 字符串类型,Django Admin以及ModelForm中提供验证机制
    
        IPAddressField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
    
        GenericIPAddressField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
            - 参数:
                protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
                unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both"
    
        URLField(CharField)
            - 字符串类型,Django Admin以及ModelForm中提供验证 URL
    
        SlugField(CharField)
            - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
    
        CommaSeparatedIntegerField(CharField)
            - 字符串类型,格式必须为逗号分割的数字
    
        UUIDField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
    
        FilePathField(Field)
            - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
            - 参数:
                    path,                      文件夹路径
                    match=None,                正则匹配
                    recursive=False,           递归下面的文件夹
                    allow_files=True,          允许文件
                    allow_folders=False,       允许文件夹
    
        FileField(Field)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
    
        ImageField(FileField)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
                width_field=None,   上传图片的高度保存的数据库字段名(字符串)
                height_field=None   上传图片的宽度保存的数据库字段名(字符串)
    
        DateTimeField(DateField)
            - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
    
        DateField(DateTimeCheckMixin, Field)
            - 日期格式      YYYY-MM-DD
    
        TimeField(DateTimeCheckMixin, Field)
            - 时间格式      HH:MM[:ss[.uuuuuu]]
    
        DurationField(Field)
            - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
    
        FloatField(Field)
            - 浮点型
    
        DecimalField(Field)
            - 10进制小数
            - 参数:
                max_digits,小数总长度
                decimal_places,小数位长度
    
        BinaryField(Field)
            - 二进制类型
    
    字段合集
    字段合集(争取记忆 
    """
    时间间隔
    """
    import datetime
    
    now = datetime.datetime.now()  # 你领了一张有效期为7天的优惠券
    print(now)    #  2020-04-25 18:02:41.800477
    # 时间间隔
    d7 = datetime.timedelta(weeks=52)
    # 求失效时间
    ret = now + d7
    print(ret)    #  2021-04-24 18:02:41.800477
    时间间隔 

    2、自定义字段(了解为主)

    class UnsignedIntegerField(models.IntegerField):
        def db_type(self, connection):
            return 'integer UNSIGNED'
    class FixedCharField(models.Field):
        """
        自定义的char类型的字段类
        """
        def __init__(self, max_length, *args, **kwargs):
            super().__init__(max_length=max_length, *args, **kwargs)
            self.length = max_length
    
        def db_type(self, connection):
            """
            限定生成数据库表的字段类型为char,长度为length指定的值
            """
            return 'char(%s)' % self.length
    
    
    class Class(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=25)
        # 使用上面自定义的char类型的字段
        cname = FixedCharField(max_length=25)

    3、字段参数

    null
    用于表示某个字段可以为空。
    
    unique
    如果设置为unique=True 则该字段在此表中必须是唯一的 。
    
    db_index
    如果db_index=True 则代表着为此字段设置数据库索引。
    
    default
    为该字段设置默认值。

    4、时间字段独有

        DateField  年月日
    DateTimeField  年月日时分秒
        auto_now:  每次操作改数据都会自动更新时间
    auto_now_add:  新增数据的时候会将当前时间自动添加,后续的修改该字段不会自动更新

    5、关系字段

    (1)ForeignKey

    外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 '一对多'中''的一方。

    ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。

    字段参数:

                    to: 设置要关联的表
               to_field: 设置要关联的表的字段
           related_name: 反向操作时,使用的字段名,用于代替原反向查询时的'表名_set'     db_constraint: 是否在数据库中创建外键约束,默认为True。
    related_query_name: 反向查询操作时,使用的连接前缀,用于替换表名。 
    当删除关联表中的数据时,当前表与其关联的行的行为。
    
    models.CASCADE
    删除关联数据,与之关联也删除
    
    
    models.DO_NOTHING
    删除关联数据,引发错误IntegrityError
    
    
    models.PROTECT
    删除关联数据,引发错误ProtectedError
    
    
    models.SET_NULL
    删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
    
    
    models.SET_DEFAULT
    删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
    
    
    models.SET
    
    删除关联数据,
    a. 与之关联的值设置为指定值,设置:models.SET(值)
    b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
    on_delete

    为什么要使用ForeignKey? 

        使用它可以做约束,而且节约硬盘,如果没有它所有数据都在一张表,浪费硬盘;
        但使用FK降低到了查询速度(单表查询速度快)
        数据量比较大,不会使用FK,允许出现数据冗余。 

    三、元信息

    ORM对应的类里面包含另一个Meta类,而Meta类封装了一些数据库的信息。主要字段如下:

    db_table
    ORM在数据库中的表名默认是 app_类名,可以通过db_table可以重写表名。
    
    index_together
    联合索引。
    
    unique_together
    联合唯一索引。
    
    ordering
    指定默认按什么字段排序。
    只有设置了该属性,我们查询到的结果才可以被reverse()。 
    class Person(models.Model):
        name = models.CharField(max_length=32)
        new_name = FixedCharField(max_length=64, default="张三")  # char(64)
        age = models.IntegerField(default=18)
        birthday = models.DateField(auto_now_add=True)
    
        def __str__(self):
            return self.name
    
        class Meta:
            db_table = "person"
    db_table的使用 
    class Author2Book(models.Model):
        id = models.AutoField(primary_key=True)
        # 作者id
        author = models.ForeignKey(to="Author")
        # 书id
        book = models.ForeignKey(to="Book")
    
        # memo
        memo = models.CharField(max_length=64, null=True)
    
        class Meta:
            # 建立唯一约束
            unique_together = ("author", "book")
    unique_together的使用
    class Person(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField(default=18)
        birthday = models.DateField(auto_now_add=True)
    
        def __str__(self):
            return "<Person Object:{}>".format(self.name)
    
        class Meta:
            ordering = ("birthday",)
    ordering的使用 

    四、Django ORM相关操作

    参考

    1、如何在一个Python脚本或文件中 加载Django项目的配置和变量信息

    import os
    
    if __name__ == '__main__':
        # 加载Django项目的配置信息
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ormday69.settings")
        # 导入Django,并启动Django项目
        import django
        django.setup()
    
        from app01 import models  #这一句话必须在这里导入

    2、django终端打印sql语句配置的参数

    # 如果你想知道你对数据库进行操作时,Django内部到底是怎么执行它的sql语句时可以加下面的配置来查看
    # 在Django项目的settings.py文件中,在最后复制粘贴如下代码:
    
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }
    
    # 配置好之后,再执行任何对数据库进行操作的语句时,会自动将Django执行的sql语句打印到pycharm终端上
    
    
    # 补充:除了配置外,还可以通过一点.query即可查看查询语句:
    user_obj = models.User.objects.all()
    print(user_obj.query)

     补充:跟性能相关的sql

    only/defer 与 selected_related、prefetch_related 

    #only:只取model表中的某n列
    queryset = [object,object]
    result = model.User.objects.all().only('id','name')
    for item in result:
    print(item.id,item.name)  #想取什么要在only中先获取,不然查询性能会降低
    #defer:不取表中的哪些列
    
    #seleted_related与prefetch_related
    class Depart(models.Model): 5个部门
        title = models.CharField(...)
    
    class User(models.Model):   10个用户,这里假设10个用户使用了2个部门
        name = models.CharField(...)
        email = models.CharField(...)
        dp = models.FK(Depart)
    
    1.以前的你:11次单表查询
    
        result = User.objects.all()
        for item in result:
            print(item.name,item.dp.title)
    
    2. seleted_related,主动做连表查询(1次连表) 支持 one to one ,ForeignKey
    
        result = User.objects.all().seleted_related('dp')
        for item in result:
            print(item.name,item.dp.title)
    
        问题:如果连表多,性能越来越差。
    
    3. prefetch_related:2次单表查询   支持many to many
        # select * from user ;
        # 通过python代码获取:dp_id = [1,2]
        # select * from depart where id in dp_id
        result = User.objects.all().prefetch_related('dp')
        for item in result:
            print(item.name,item.dp.title)

    ORM单表、多表操作点我

  • 相关阅读:
    linux编程 给线程起名字
    c语言的__packed__
    LINUX 命令行编辑快捷键
    linux关于bashrc与profile的区别(转)
    linux查看和修改PATH环境变量的方法
    linux 线程 pthread_create 源码 剖析
    你真的了解【HashMap】么?-一
    Oracle 基础概念
    Java数据库连接池
    JVM内存模型与垃圾回收
  • 原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/12774021.html
Copyright © 2020-2023  润新知