zoukankan      html  css  js  c++  java
  • Django框架之ORM常用字段和参数、单表操作

    一 Django ORM常用字段和参数

    常用字段

    AutoField

    映射到数据库中是 int 类型,int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。

    IntegerField

    一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,)

    CharField

    字符类型,必须提供max_length参数, max_length表示字符长度。这个类型在使用的时候必须要指定最大的长度

    这里需要知道的是Django中的CharField对应的MySQL数据库中的varchar类型,没有设置对应char类型的字段,但是Django允许我们自定义新的字段,下面我来自定义对应于数据库的char类型

    from django.db import models
    
    # Create your models here.
    # Django中没有对应的char类型字段,但是我们可以自己创建
    class FixCharField(models.Field):
        '''
        自定义的char类型的字段类
        '''
        def __init__(self,max_length,*args,**kwargs):
            self.max_length=max_length
            super().__init__(max_length=max_length,*args,**kwargs)
    
        def db_type(self, connection):
            '''
            限定生成的数据库表字段类型char,长度为max_length指定的值
            :param connection:
            :return:
            '''
            return 'char(%s)'%self.max_length
    # 应用上面自定义的char类型
    class Class(models.Model):
        id=models.AutoField(primary_key=True)
        title=models.CharField(max_length=32)
        class_name=FixCharField(max_length=16)
        gender_choice=((1,''),(2,''),(3,'保密'))
        gender=models.SmallIntegerField(choices=gender_choice,default=3)
    自定义使用

    DateField

    日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。

    DateTimeField

    日期时间字段,格式 YYYY-MM-DD HH:MM:ss[.uuuuuu],相当于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)
            - 二进制类型
    字段合集

    OM字段与MySQL对应关系:

      '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)',
    OM字段与MySQL对应关系:

    ORM字段参数

    null

    用于表示某个字段可以为空。

    unique

    如果设置为unique=True 则该字段在此表中必须是唯一的 。

    db_index

    如果db_index=True 则代表着为此字段设置索引。

    default

    为该字段设置默认值。

    DateField和DateTimeField

    auto_now_add

    配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

    auto_now

    配置上auto_now=True,每次更新数据记录的时候会更新该字段。

    关系字段

    ForeignKey

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

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

    字段参数:

    to:设置要关联的表
    
    to_field:设置要关联的表的字段
    related_query_name:反向查询操作时,使用的连接前缀,用于替换表名。
    on_delete:当删除关联表中的数据时,当前表与其关联的行的行为。

       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(可执行对象)
    db_constraint: 是否在数据库中创建外键约束,默认为True,可以设置为False。
       True:建立外键,默认是True
       False:不建立外键
       好处:不会出现脏数据
       坏处:插入的时候,效率低
       企业中:通常不建立,程序员控制

    其余字段参数:

    def func():
        return 10
    
    class MyModel(models.Model):
        user = models.ForeignKey(
            to="User",
            to_field="id",
            on_delete=models.SET(func)
        )

    OneToOneField

    一对一字段。

    通常一对一字段用来扩展已有字段。(通俗的说就是一个人的所有信息不是放在一张表里面的,简单的信息一张表,隐私的信息另一张表,之间通过一对一外键关联)

    字段参数:

    to:设置要关联的表。
    
    to_field:设置要关联的字段。
    
    on_delete:当删除关联表中的数据时,当前表与其关联的行的行为。

    ManyToManyField

    用于表示多对多的关联关系。在数据库中通过第三张表来建立关联关系

    字段参数:

    to:设置要关联的表
    
    to_field:设置要关联的表的字段
    
    related_query_name:反向查询操作时,使用的连接前缀,用于替换表名。同ForeignKey字段。
    
    symmetrical:仅用于多对多自关联时,指定内部是否创建反向操作的字段。默认为True。
    
    through::设置关联的字段。手动创建第三张表,指定通过哪个表
    
    through_fields:设置关联的字段。关联字段是什么
    
    db_table:默认创建第三张表时,数据库中表的名

    多对多关系建立的三种方式

    第一种:自动创建(常用:第三张表没有其他字段)

    class Book(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
    
    
    # 通过ORM自带的ManyToManyField自动创建第三张表
    class Author(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者姓名")
        books = models.ManyToManyField(to="Book", related_name="authors")

    第二种:手动创建第三张表(比较常用:第三张表有多余字段)

    class Book1(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
    
    
    # 自己创建第三张表,并通过ManyToManyField指定关联
    class Author1(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者姓名")
        books = models.ManyToManyField(to="Book1", through="Author2Book", through_fields=("author", "book"))
        # through_fields 元组的第一个值是ManyToManyField所在的表去中间表通过那个字段,就写在第一个位置
    
    
    class Author2Book(models.Model):
        author = models.ForeignKey(to="Author1")
        book = models.ForeignKey(to="Book1")
        
    
    
    ##基于对象的跨表查,还能继续使用
    ## 基于双下划綫连表查
    ## 原来的多对多操作api用不了了,需要手动操作

    第三中:完全手动写第三张表

    class Book1(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
        
    
    class Author1(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者姓名")
    
    
    # 自己创建第三张表,分别通过外键关联书和作者
    class Author2Book1(models.Model):
        author = models.ForeignKey(to="Author")
        book = models.ForeignKey(to="Book")

    Meta 元信息

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

    db_table:ORM在数据库中的表名默认是 app_类名,可以通过db_table可以重写表名。
    
    index_together:联合索引。
    
    unique_together:联合唯一索引。
    
    ordering:指定默认按什么字段排序。
    
    只有设置了该属性,我们查询到的结果才可以被reverse()。
    # 在每一个模型类中都可以写
    class Publish(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        addr = models.CharField(max_length=32)
        email = models.EmailField()  
    
        class Meta: #元信息
            db_table='lqz_publish'  # 表名
            index_together=('name','addr')  # 多个字段联合索引
            unique_together=('name','addr') # 联合唯一
            ordering=('id', ) # 默认以哪个字段排序
    示例

    二 在Python脚本中调用Django环境

    ps:
        1.pycharm链接数据库都需要提前下载对应的驱动
        2.自带的sqlite3对日期格式数据不敏感
            如果后续业务需要使用日期辅助筛选数据那么不推荐使用sqlite3
    
    django测试环境搭建 :      
    # 方式1:任意创建一个py文件,eg:test.py 在该文件内书写固定的配置
    import os
    if __name__ == "__main__":
        # 加载配置文件,跑django的项目,最开始就是把配置文件加载上
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day06.settings")
        import django  # 安装了django模块,就可以import
        django.setup()  # 使用环境变量中的配置文件,跑django
        
        from app01 import models  # 单独测试django py文件

    # 方式2:直接使用pycharm提供的python console

    三 Django终端打印SQL语句

    # 1 queryset对象.query
    # 2 通过日志,如下,配置到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',
            },
        }
    }

    四 单表查询关键字

    准备书籍表

    # models.py
    class Books(models.Model):
        title = models.CharField(verbose_name='书名',max_length=32)
        price = models.CharField(verbose_name='价格',max_length=32)
        publish_time = models.DateTimeField(verbose_name='日期',auto_now_add=True)
        
         def __str__(self):  # 改变对象的字符串显示,打印对象自动触发
            return self.title  # 返回值
    # 增加
        res = models.Books.objects.create(title='人性的弱点',price=687.90)
        print(res.title)   # 人性的弱点 
        '''create返回值就是当前被创建的数据对象'''
    # 查询
        res = models.Books.objects.all()
        print(res.query) # query查看当前orm内部对应的原生sql语句
        res = models.Books.objects.filter()
        print(res.query)
        res = models.Books.objects.filter(title='jason')
        print(res)
        """filter括号内可以放多个参数 默认是and关系  推荐使用  条件不符合不会报错"""
        
        res1 = models.Books.objects.get(title='jason')
        print(res1)
        """get括号内可以放多个参数 默认是and关系  不推荐使用  条件不符合直接报错"""
    # 修改
        # 方式一:(推荐)
        res = models.Books.objects.filter(pk=1).update(price=666.66)
        print(res)  # 返回值是受影响的行数
        # 方式二:(少用)
        book_obj = models.Books.objects.filter(pk=2).first()
        book_obj.price = 999.66
        book_obj.save()  # 效率低(所有字段重新写一遍)
        """pk能够自动查找到当前表的主键字段 我们不需要查看当前表主键字段名"""
    #
        models.Books.objects.filter(pk=1).delete()

    QuerySet对象方法

    query 查看ORM内部对应的SQL语句

    必知必会13条

    1. all() 查询所有结果

      res = models.Books.objects.all()
      print(res)
      res1 = models.Books.objects.all()[0:2]  # 切片
      print(res1)

     2. filter() 它包含了与所给筛选条件相匹配的数据对象

      res = models.Books.objects.filter(title='修心三不')
      print(res)
      res = models.Books.objects.filter(title='jason')
      print(res)

    3. get() 它包含了与所给筛选条件相匹配的数据对象本身

      res = models.Books.objects.get(title='修心三不')
      print(res)
      res1 = models.Books.objects.get(title='jason')
      print(res1)

    4. first() 取第一个数据对象

      res = models.Books.objects.all().first() # 取queryset的第一个元素
      print(res)
      res1 = models.Books.objects.all()[0]  # 等同于这个 
      print(res1)

    5. last() 取最后一个数据对象

      res = models.Books.objects.all().last()
      print(res)

    6. values() 获取数据指定字段的值

      res = models.Books.objects.all().values('title','publish_time') # 加all
      res1 = models.Books.objects.values('title','publish_time') # 不加all
      print(res,res1) # 获取的值一样
      """all()加不加都表示所有数据  values获取的结果 类似于列表套字典"""

    7. values_list() 获取数据指定字段的值

      res = models.Books.objects.values_list('title', 'publish_time')
      print(res)
      """values_list获取的结果 类似于列表套元组"""

    8. order_by() 排序

      res = models.Books.objects.order_by('price')  # 按价格排序,默认是升序
      print(res)
      res1 = models.Books.objects.order_by('-price')  # 减号降序
      print(res1)

    9. count() 计数

      res = models.Books.objects.count()  # 统计数据条数
      print(res)

    10. distinct() 去重

      res = models.Books.objects.all().distinct()
      print(res)
      res1 = models.Books.objects.values('title').distinct()
      print(res1)
      """去重的前提是数据必须是一模一样  一定不能忽略主键"""

    11. exclude() 它包含了与所给筛选条件不匹配的对象,排除什么什么在外

      res = models.Books.objects.exclude(title='人性的弱点')
      print(res.query)

    12. reverse() 反转,对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)

      res = models.Books.objects.all()
      print(res)
      res1 = models.Books.objects.reverse()
      print(res1)
      res2 = models.Books.objects.order_by('price').reverse()
      print(res2)
      """reverse需要先排序之后才能反转"""

    13. exists() 判断是否有数据 ,如果QuerySet包含数据,就返回True,否则返回False

      res = models.Books.objects.all().exists()
      print(res)
    # True

    总结

    返回QuerySet对象的方法有:
    all()
    filter()
    exclude()
    order_by()
    reverse()
    distinct()
    特殊QuerySet
    values # 返回一个可迭代的字典序列
    values_list # 返回一个可迭代的元组序列
    
    返回具体对象的方法有:
    get()
    first()
    last()
    
    返回数字的方法有:
    count()
    
    返回布尔值的方法有:
    exists()

    范围查询(神奇的双下划线查询)

    1.查询价格大于700的书籍 
        res = models.Books.objects.filter(price__gt=700) # gt表示大于
        print(res)
        print(res.query)
        
    2.查询价格小于700的书籍
        res = models.Books.objects.filter(price__lt=700) # lt表示小于
        print(res)
        print(res.query)
     价格大于等于700 小于等于700
        res1 = models.Books.objects.filter(price__gte=700)
        res2 = models.Books.objects.filter(price__lte=700)
        print(res1.query,res2.query)
        
    3.查询价格要么是666.66 要么是999.66 要么是10000
        res = models.Books.objects.filter(price__in=[666.66,999.66,10000])
        print(res)
        """python对数字不是很敏感 精确度不高  很多时候我们会采取字符串存储数字类型"""
        
    4.查询价格在500到800之间的
        res = models.Books.objects.filter(price__range=(500,800))
        print(res.query)
    
    5.查询书名中包含字母s的书
        res = models.Books.objects.filter(title__contains='s')  # 区分大小写
        print(res.query)
        res = models.Books.objects.filter(title__icontains='s')  # 区分大小写
        print(res)
    
    6.查询出版日期是2021的书
        res = models.Books.objects.filter(publish_time__year=2021) # year代表年
        print(res.query)
        
    7.查询出版日期是3月的书
        res = models.Books.objects.filter(publish_time__month=3) # month代表月
        print(res)
    从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
  • 相关阅读:
    Windows Azure Storage (17) Azure Storage读取访问地域冗余(Read Access – Geo Redundant Storage, RA-GRS)
    SQL Azure (15) SQL Azure 新的规格
    Azure China (5) 管理Azure China Powershell
    Azure China (4) 管理Azure China Storage Account
    Azure China (3) 使用Visual Studio 2013证书发布Cloud Service至Azure China
    Azure China (2) Azure China管理界面初探
    Azure China (1) Azure公有云落地中国
    SQL Azure (14) 将云端SQL Azure中的数据库备份到本地SQL Server
    [New Portal]Windows Azure Virtual Machine (23) 使用Storage Space,提高Virtual Machine磁盘的IOPS
    Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())的注意点
  • 原文地址:https://www.cnblogs.com/gfeng/p/14568158.html
Copyright © 2011-2022 走看看