• [Python] Django框架入门2——深入模型


    说明:

      本文主要深入了解模型(models.py),涉及ORM简介、模型定义、模型成员、模型查询、自连接等。需要一定基础,可以先走一走基本入门流程。

      附录一使用mysql数据库,附录二Django开发流程。

    目录:

      一、ORM简介

        ORM简介 

      二、模型定义

        1、基本模型

        2、字段类型

        3、字段选项

        4、关系

        5、元选项

      三、模型成员

        1、查询

        2、Django默认的管理器

        3、自定义管理器

      四、模型查询

        1、查询集

        2、字段查询

        3、

      五、自连接

      附录一:使用mysql

      附录二:Django开发流程

      

    一、ORM简介(引用,详情请查阅相关文档)

      ORM(Object Relational Mapping)即是"对象-关系-映射"的简称,是MVC框架一个重要的部分(Django也支持ORM),它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置可以轻松更换数据库。

      ORM的作用:

        根据对象的类型生成表结构

        将对象、列表的操作,转换成sql语句

        将sql查询到的结果转换为对象、列表

      使用ORM主要方便开发人员,极大减轻开发人员的工作量,避免手写sql语句出现的各种问题。

      Django中的模型包含存储的字段和约束,对应着数据库中唯一的表。

      

    二、模型定义

      1、基本的模型  

     1 from django.db import models
     2 
     3 
     4 class BookInfo(models.Model):
     5     """
     6         图书类 => 图书表(booktest_bookinfo)
     7     """
     8     # 图书标题 => varchar(20)
     9     btitle = models.CharField(max_length=20)
    10     # 发布日期 => datetime
    11     bpub_date = models.DateTimeField()
    12     # 阅读数 => int(11)
    13     bread = models.IntegerField(default=0)
    14     # 评论数 => int(11)
    15     bcomment = models.IntegerField(default=0)
    16     # 是否删除 => tinyint
    17     isDelete = models.BooleanField(default=False)
    18 
    19     def __str__(self):
    20         return self.btitle
    21 
    22 
    23 class HeroInfo(models.Model):
    24     """
    25         英雄类 => 英雄表(booktest_heroinfo)
    26     """
    27     # 英雄名字 => varchar(20)
    28     hname = models.CharField(max_length=20)
    29     # 性别 => tinyint
    30     hgender = models.BooleanField(default=True)
    31     # 简介 => varchar(1000)
    32     hcontent = models.CharField(max_length=1000)
    33     # 是否删除 => tinyint
    34     isDelete = models.BooleanField(default=False)
    35     # 外键 => int(11)
    36     hbook = models.ForeignKey(BookInfo)  # 外键

        说明:

          定义属性时,需要字段类型

          字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models中

          使用方式:见上面代码

          对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False

            

      2、字段类型(引用)

        表单控制是指在django管理站点的前端显示。

        AutoField:根据ID自动增长的IntegerField,一般无需指定,django会自动添加到模型中,数据库类型为 int(11)。

        BooleanFidld:true/false字段,此字段的默认表单控件是CheckboxInput,数据库类型为 tinyint。

        NullBooleanField:支持null、true、false三种值,数据库类型为 tinyint。

        CharField(max_length=字符长度):字符串,默认的表单控件是TextInput,数据库类型为 varchar(字符长度)。

        TextField:大文本字段,一般字符长度超过4k使用,默认的表单控件是Textarea,数据库类型为 varchar(字符长度)。

        IntegerField:整数,数据库类型为 int。

        DecimalField(max_digits=None, decimal_places=None):使用python的Decimal实例表示的十进制浮点数,数据库类型为 decimal(P, D):

          DecimalField.max_digits:位数总数

             DecimalField.decimal_places:小数点后的数字位数。

        FloatField:使用python的float实例来标识的浮点数。

        DateField([auto_now=False, auto_noew_add=False]):使用pyhton的datetime.date实例表示日期。

          参数auto_now:每次保存对象时,自动设置该字段为当前时间,用于保存"最后一次修改"的时间戳,他总是使用当前的日期,默认为false

          参数auto_now_add:当对象第一次被创建时自动设置当前时间,用于保存创建的时间戳,它总是使用当前日期,默认为false

          该字段默认对应的表单控件是TextInput

          auto_now、auto_now_add、default 这些设置是相互排斥的,他们之间任何组合将会发生错误的结果 。

        TimeField:使用python的datetime.time实例表示的时间,参数同DatEField。

        DateTimeField:使用python的datetime.datetime实例表示的日期和时间,参数同DateField

        FileField:一个上传文件的字段,一般不会把文件保存在数据库中,建议保存文件上传的路径。

        ImageField:继承FieldField的所有属性和方法,当对上传的对象进行校验,确保上传是有些的image。

      3、字段选项

        使用:title = models.CharFidle(null=True)

        null:如果为True,Django将空值以NULL存储到数据库中,默认值是False。

        blank:如果为True,则该字段允许为空,默认值是False。

        null与blank对比:null是数据库范畴的概念,blank是表单验证范畴的。

        db_column:字段的名称,如果为指定,则使用属性的名称。

        db_index:如果为True,则在表中会为此字段创建索引

        default:默认值。

        primary_key:如果为True,则该字段会成为模型的主键字段。

        unique:如果为True,表示这个字段在表中必须有唯一值。

     

      4、关系

        关系的类型有如下:

          ForeignKey:一对多,将字段定义在多的端中(如上面基本模型的代码)。

          ManyToManyField:多对多,将字段定义在两端中

          OneToOneField:一对一,将字段定义在任意一端中。

        访问方式:

          用一访问多:对象.模型类小写_set 

            bookinfo.heroinfo_set

          用一访问一:对象.模型类小写

            heroinfo.bookinfo

            heroinfo.book_id

      

      5、元选项

        在模型类中定义类Meta,用于设置元信息    

    1 class BookInfo(models.Model):
    2     # 元选项
    3     class Meta:
    4         # 数据表名
    5         db_table = 'bookinfo'
    6         # 对象默认排序字段,正序
    7         ordering = ['id']
    8         # ordering = ['-id']    # 倒序

    三、模型成员

      1、查询数据

         book_list = BookInfo.objects.all() 

      

      2、Django默认的管理器

        objects:是Manager类型的对象,用于与数据库进行交互。

        当定义模型时没有指定管理器,则Django会为模型类提供一个名为objects的管理器。

        支持明确指定管理器(如果自己指定manager,django不再为模型类生成名为objects的默认管理器):   

    1 class BookInfo(models.Model):
    2     manager1 = models.Manager()

      3、自定义管理器

        管理器是Django的模型进行数据库的查询操作的接口,Django应用的每个模型都拥有至少一个管理器。

        自定义管理器主要用于以下两种情况:

          情况一:修改管理器返回的原始查询集:重写get_query_set()方法。

          情况二:向管理器中添加额外的方法

        代码如下(manager2就是自定义的管理器):

     1 class BookInfoManager(models.Manager):
     2     """
     3         自定义管理器
     4     """
     5     # 情况一:更改默认查询结果,只查未删除的数据
     6     def get_queryset(self):
     7         return super(BookInfoManager, self).get_queryset().filter(isDelete=False)
     8 
     9     # 情况二:定义模型类的创建方法
    10     def create(cls, btitle, bpub_date):
    11         b = BookInfo()
    12         b.btitle = btitle
    13         b.bpub_date = bpub_date
    14         b.bread = 0
    15         b.bcomment = 0
    16         b.isDelete = False
    17         return b
    18 
    19 
    20 class BookInfo(models.Model):
    21     btitle = models.CharField(max_length=20)
    22     bpub_date = models.DateTimeField()
    23     bread = models.IntegerField(default=0)
    24     bcomment = models.IntegerField(default=0)
    25     isDelete = models.BooleanField(default=False)
    26 
    27     def __str__(self):
    28         return self.btitle
    29 
    30     # 管理器
    31     manager1 = models.Manager()
    32     manager2 = BookInfoManager()    

         情况一的测试结果如下:

          

            

         情况二的测试结果如下(简化创建对象的过程:new->赋值->save):

           

            

    四、模型查询

      1、查询集

        在管理器上调用过滤器方法返回查询集。

        查询集经过过滤筛选后返回信的查询集,因此可以写成链式过滤。

        惰性执行:创建查询集不会带来任何数据的访问,直到调用数据的时候(迭代、序列号、与if合用),才会访问数据库。

        返回查询集的方法,称为过滤器:all()filter()exclude()order_by()values()

        写法:manager.filter(键1=值1, 键2=值2) => manager.filter(键1=值1).filter(键2=值2)

          

        返回单个值的方法:

          get():返回单个满足添加的对象

            如果未找到会引发"模型类 DoesNotExist"异常

            如果多条被返回,会引发"模型类 MultipleObjectsReturn"异常

          count():返回当前查询的总条数

          first():返回第一个对象

          last():返回最后一个对象

          exists():判断查询集中是否有数据,有则返回True

        

        限制查询集:

          查询集返回列表,可以使用下标的方式进行限制,等同于sql中limit和offset子句

          注意:不支持负数索引

          如果下标返回一个新的查询集,不会立刻执行查询

          如果获取一个对象,直接使用[0],等同于[0:1].get()。但是如果没有数据,[0]引发IndexError异常,[0:1].get()引发DoesNotExist异常。

          

        查询集的缓存

          每个查询集都包含一个缓存来最小化对数据库的访问。

          在新建的查询集中,缓存为空,首次对查询集求值时,会发生数据库查询,Django会将查询的结果存在查询集的缓存中,并返回请求的结果,接下来对查询集求值将重用缓存的结果。

          情况一:构建两个查询集,无法重用缓存,每次查询都会与数据库进行交互,增加数据库的负载

          

          情况二:两次循环使用同一个查询集,第二次使用缓存中的数据

            

          何时查询集不会被缓存:当只对查询集的部分进行求值时,会检查缓存,但是如果这部分不再缓存中,那么接下来查询返回的几率将不会被缓存,这意味着使用索引来限制查询集将不会填充缓存,如果这部分数据已经被缓存,则直接使用缓存中的数据。

    1 query = BookInfo.objects.all()
    2 for each in query    # 缓存
    3 for each in query[0,10] # 不缓存
    4 # 使用子集不缓存

      2、字段查询:比较运算符,F对象,Q对象

        实现where子句,作为方法filter()、exclude()、get()的参数。

        语法:属性名__比较运算符=值,__ 表示两个下划线,左侧是属性名称,右侧是比较类型。

        对于外键:使用 "属性名__id" 表示外键原始值

        转义:like语句中使用%与_,匹配数据中的%与_,在过滤器中直接写:

          filter(title__contains="%")  => WHERE `title` LIKE '%\%%'

        

        比较运算符

          exact:表示判等,大小写敏感,如果没有写 “比较运算符”,表示判等:

            filter(isDelete=False) => WHERE `isDelete` = 0

          contains:是否包含。大小写敏感:

            exclude(btitle__contains='传') => WHERE `btitle`  LIKE '%传%'

          startswhitendswith:以value开头或结尾,大小写敏感:

            exclude(btitle__endswith='传') => WHERE `btitle` LIKE '%传'

            exclude(btitle__startswith='传') => WHERE `btitle` LIKE '传%'

          isnullisnotnull:是否为null:

            filter(btitle__isnull=False) => WHERE `btitle` != null

          在前面加 i 表示不区分大小写,如:iexact、icontains、istartswith、iendswith

        

          in:是否包含在范围内:

            filter(pk__in=[1,2,3]) => WHERE `id`  IN (1, 2, 3)

          gtgteltlte:大于、大于等于、小于、小于等于

            filter(id__gt=3) => WHERE `id` > 3

            filter(id__lte=5) => WHERE `id` <= 5

          yearmonthdayweek_dayhourminutesecond:对日期时间类型的属性进行运算:

            filter(bpub_date__year=1980)  

            filter(bpub_date__gt=date(1980, 12, 31))

          跨关系的查询:处理join查询:

            filter(heroinfo__hcontent__contains='八') => SELECT * FROM `bookinfo` JOIN `heroinfo` ON `bookinfo`.`id`=`heroinfo`.`hbook` WHERE `heroinfo`.`hcontent` LIKE '%八%'

          聚合函数

            使用aggregate()函数返回聚合函数的值

            函数:Avg、Count、Max、Min、Sum

    from django.db.models import Max
    maxDate = BookInfo.objects.aggregate(Max('bpub_date'))

            count的一般用法:count = list.count()

          

          F对象:构建等号右侧字段:

            可以使用模型的字段A与字段B进行比较,如果A在等号左侧,则B出现在等号的右侧时需要通过F对象构造:

              list.filter(bread__gt=F('bcomment')) => WHERE `bread` > `bcomment`

            Django支持对F对象使用算数运算:

              list.filter(bread__gte=F('bcomment')) => WHERE `bread` >= `bcomment` * 3

            F()对象还可以写作“模型类__列名”进行关联查询:

              list.filter(isDelete=F('heroinfo__isDelete')) => WHERE `bookinfo`.`isDelete` = `heroinfo`.`isDelete`

            对于date/time字段,可与timedelta()进行运算:

              list.filter(bpub_date__lt=F('bpub_date') + timedelta(days=1))

          

          Q对象:处理逻辑或:

            过滤器方法中关键字参数查询,会合并为And进行查询。

            需要进行or查询,使用Q对象

            Q对象(django.db.models.Q)用于封装一组关键字参数,这些关键字参数与“比较运算符”中的相同  

    from django.db.models import Q
    list.filter(Q(pk__lt=6))

             Q对象可以使用&(and)、|(or)操作符组合起来

             当操作符应用在两个Q对象时,会产生一个新的Q对象

     list.filter(pk__lt=6).filter(bcomment__gt=10) # WHERE `id` < 6 AND `bcomment` > 10
     list.filter(Q(pk__lt=6) | Q(bcomment__gt=10))  # WHERE `id` < 6 OR `bcomment` > 10

            使用~(not)操作符在Q对象前表示取反 

               list.filter(~Q(pk__lt=6)) 

            

            可以使用&|~结合括号进行分组,构造复杂的Q对象

            过滤函数可以传递一个或多个Q对象作为位置参数,如果有多个Q对象,这些参数的逻辑为and

            过滤器函数可以混合使用Q对象和关键字参数,所有参数都将And在一起,Q对象必须位于关键字参数的前面。

    五、自连接

      自连接主要应用于无限级分类等。

    1 class AreaInfo(models.Model):
    2     atitle = models.CharFields(max_lenth=20)
    3     aParent = mdoels.ForeignKey('self', null=True, blank=True)

      访问关联对象:

        上级:area.aParent

        下级:area.areainfo_set.all()

    附录一:使用mysql数据库

      1、安装插件:python-mysql 或 mysqlclient

        我的电脑安装的是python3.5,通过wheel安装mysqlclient,下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient

      2、修改配置文件

          

     附录二:Django开发流程

      1、创建项目:执行指令:django-admin startproject [项目名]

      2、进入项目目录,创建应用:执行指令:python manager.py startapp [应用名]

      3、进入应用目录,在models.py中定义模型类,要求继承自models.Model

      4、把应用加入settings.py文件中的installed_app项中

      5、生成迁移文件,执行指令:python manager.py makemigrations

      6、执行迁移生成表,执行指令:python manager.py migrate

      7、使用模型类进行crud操作

      *、使用数据库生成模型类

        python manager.py inspectdb > booktest/models.py

     

  • 相关阅读:
    windbg javascript脚本--将内存内容保存到文件
    js补全前置零
    javascript打印对象(object)
    c++ primer学习指导(23)--4.2算术运算符
    c++ primer学习指导(22)--3.2.1直接初始化和拷贝初始化
    c++ primer学习指导(21)--2.2.4名字的作用域
    c++ primer学习指导(19)--2.1.2类型转换
    c++ primer学习指导(18)-- 2.1.1算术类型
    搭建sock5代理
    Centos 6 yum源
  • 原文地址:https://www.cnblogs.com/reader/p/9452488.html
Copyright © 2020-2023  润新知