zoukankan      html  css  js  c++  java
  • 二、Django模型

    1、Django框架中的ORM示意图

      

     2、使用MySQL数据库

      2.1 更换默认数据库

        进入settings.py文件,找到DATABASES项,默认使用SQLite3数据库

        

        修改为使用MySQL数据库:将引擎改为mysql,提供连接的主机HOST、端口PORT,数据库名NAME,用户名USER,密码PASSWORD。

        

        注意:其中的数据库test_demo Django框架不会自动生成,需要我们自己进入mysql数据库区去创建。

        

      2.2 使用mysql

        2.2.1 写入模型类

        

        2.2.2 生成迁移文件时报错

          python manage.py makemigrations

          

          当数据库切换成mysql后,需要安装pymysql模块之后,Django框架才可以操作mysql数据库:pip install pymysql

          安装成功后,还需要在settings.py同级文件__init__.py中写入:

          import pymysql

          pymysql.install_as_MySQLdb()

          然后执行迁移:

          python manage.py makemigrations

          python manage.py migrate

          

          打开数据的命令行,查看当前所有表的内容:
          

           表bookinfo结构:

          

          表booktest_heroinfo结构:

          

           Django框架会根据关系属性生成一个关系字段,并创建外键约束。

      2.3 测试数据

        2.3.1 在数据库命令行中插入数据

    insert into booktest_bookinfo(btitle,bpub_date,bread,bcomment,isDelete) values
    ('射雕英雄传','1980-5-1',12,34,0),
    ('天龙八部','1986-7-24',36,40,0),
    ('笑傲江湖','1995-12-24',20,80,0),
    ('雪山飞狐','1987-11-11',58,24,0);
    
    
    insert into booktest_heroinfo(hname,hgender,hbook_id,hcomment,isDelete) values
    ('郭靖',1,1,'降龙十八掌',0),
    ('黄蓉',0,1,'打狗棍法',0),
    ('黄药师',1,1,'弹指神通',0),
    ('欧阳锋',1,1,'蛤蟆功',0),
    ('梅超风',0,1,'九阴白骨爪',0),
    ('乔峰',1,2,'降龙十八掌',0),
    ('段誉',1,2,'六脉神剑',0),
    ('虚竹',1,2,'天山六阳掌',0),
    ('王语嫣',0,2,'神仙姐姐',0),
    ('令狐冲',1,3,'独孤九剑',0),
    ('任盈盈',0,3,'弹琴',0),
    ('岳不群',1,3,'华山剑法',0),
    ('东方不败',0,3,'葵花宝典',0),
    ('胡斐',1,4,'胡家刀法',0),
    ('苗若兰',0,4,'黄衣',0),
    ('程灵素',0,4,'医术',0),
    ('袁紫衣',0,4,'六合拳',0);

        2.3.2 定义视图

    from django.shortcuts import render,redirect
    
    # Create your views here.
    from booktest.models import *
    from datetime import datetime
    
    
    # 查询所有图书并显示
    def index(request):
        list = BookInfo.objects.all()
        return render(request,'booktest/index.html',{'list':list})
    
    
    # 创建新图书
    def create(request):
        book = BookInfo()
        book.btitle='流星蝴蝶剑'
        book.bpub_date=date(1995,12,30)
        book.save()
        #转向到首页
        return redirect('/')
    
    # 逻辑删除指定编号的图书
    def delete(request,bid):
        book = BookInfo.objects.get(id=int(bid))
        book.delete()
        # 转向到首页
        return redirect('/')

        2.3.3 配置url

    from django.conf.urls import include, url
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', include(admin.site.urls)),
        #引入booktest的url配置
        url(r'^',include('booktest.urls')),
    ]

        2.3.4 创建模板

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset='UTF-8'>
        <title>复习案例</title>
    </head>
    <body>
        <a href="/create">创建</a>
        <ul>
            {%for book in list%}
                <li>{{book.btitle}}---<a href="/delete{{book.id}}">删除</a></li>
            {%endfor%}
        </ul>
    </body>
    </html>

        2.3.5 运行服务器

          python manage.py runserver

          

    3、定义属性

      Django根据属性的类型确定以下信息:

      (1)当前选择的数据库支持字段的类型

      (2)渲染管理表单时使用的默认html控件

      (3)在管理站点最低限度的验证

      Django会为表创建自动增长的主键列,每个模型只能由一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。

      默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。

      3.1 属性命名限制

        (1)不能是python的保留关键字

        (2)不允许使用连续的下划线,这是由django的查询方式决定的

        (3)定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:属性=models.字段类型(选项)

      3.2 字段类型

        使用时需要引入django.db.models包,字段类型如下:

        (1)AutoFIeld:自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。

        (2)BooleanField:布尔字段,值为True或False。

        (3)NullBooleanField:支持Null、True、False三种值。

        (4)CharField(max_length=字符长度):字符串。

            参数max_length表示最大字符个数。

        (5)TextField:大文本字段,一般超过4000个字符时使用。

        (6)IntegerField:整数。

        (7)DecimalField(max_digits=None,decimal_places=None):十进制浮点数。

            参数max_digits表示总位数

            参数decimal_places表示小数位数

        (8)FloatField:浮点数。

        (9)DateField([auto_now=False,auto_now_add=False]):日期。

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

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

            参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。

        (10)TimeField:时间,参数同DateField。

        (11)DateTimeField:日期时间,参数同DateField。

        (12)FileField:上传文件字段。

        (13)ImageField:继承于FileField,对上传的内容进行校验,确保是有效的图片。

      3.3 选项

        通过选项实现对字段的约束,选项如下:

        (1)null:如果为True,表示运行为空,默认值是False。

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

        (3)对比null和blank:null是数据库范畴的个概念,blank是表单验证范畴的。

        (4)db_column:字段的名称,如果未指定,则使用属性的名称。

        (5)db_index:若值为True,则在表中会为此字段创建索引,默认值是False。

        (6)default:默认值。

        (7)primary_key:若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用。

        (8)unique:如果为True,这个字段在表中必须有唯一值,默认值是False。

        (9)ForeignKey:外键。

     4、字段查询

      实现sql中where的功能,调用过滤器filter()、exclude()、get()。

      通过‘属性名_id’表示外键对应对象的id值。

      字段查询语法:属性名称__比较运算符=值

      说明:属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线。

      4.1 查看mysql数据库日志

        查看mysql数据库日志可以查看对数据库的操作记录。 mysql日志文件默认没有产生,需要做如下配置:sudo vim /ect/mysqlmysql.conf.d/mysql.cnf

        

        把这两行前面的#去除,然后保存并重启mysql服务:sudo service mysql restart

        使用命令打开mysql日志文件,可以实时查看数据库的日志内容:

        sudo tail -f /var/log/mysql/mysql.log

      4.2 条件运算符

        4.2.1 查询等

          exact:表示判等。

          例如:查询编号为1的图书

            list=BookInfo.objects.filter(id__exact=1)

            可简写为:

            list=BookInfo.objects.filter(id=1)

        4.2.2 模糊查询

          contains:是否包含

          说明:如果要包含%无需转义,直接写即可。

          例如:查询书名包含'传'的图书

            list=BookInfo.objects.filter(btitle__contains='传')

          startswith、endswith:以指定值开头或结尾。

          例如:查询书名以”部“结尾的图书

            list=BookInfo.objects.filter(btitle__endswith='部')

          说明:exact、contains、startswith和endswith运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith。

        4.2.3 空查询

          isnull:是否为null。

          例如:查询书名不为空的图书。

            list=BookInfo.objects.filter(btitle__isnull=False)

        4.2.4 范围查询

          in:是否包含在范围内。

          例如:查询编号为1或3或5的图书

            list=BookInfo.objects.filter(id__in=[1,3,5])

        4.2.5 比较查询

          gt、gte、lt、lte:大于、大于等于、小于、小于等于。

          例如:查询编号大于3的图书

            list=BookInfo.objects.filter(id__gt=3)

          不等于的运算符,使用exclude()过滤器。

          例如:查询编号不等于3的图书

            list=BookInfo.objects.exclude(id=3)

        4.2.6 日期查询

          year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。

          例如:查询1980年发表的图书

            list=BookInfo.objects.filter(bpub_date__year=1980)

          例如:查询1980年1月1日后发表的图书

            list=BookInfo.objects.filter(bpub_date__gt=date(1980,1,1))

      4.3 F对象

        使用条件运算符的查询都是对象的属性与常量值比较,而两个属性使用F对象比较。

        F对象被定义在django.db.models中。

        语法:F(属性名)

        例如:查询阅读量大于评论量的图书

          from django.db.models import F

          list=BookInfo.objects.filter(bread__gte=F('bcomment'))

        可以在F对象上使用算数运算。

        例如:查询阅读量大于2倍评论量的图书

          list=BookInfo.objects.filter(bread__gt=F('bcomment'*2)) 

      4.4 Q对象

        多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字。

        例如:查询阅读量大于20,并且编号小于3的图书

          list=BookInfo.objects.filter(bread__gt=20,id__lt=3)

          或list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)

        如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符,Q对象被定义在django.db.models中。

        语法:Q(属性名__运算符=值)

        例如:查询阅读量大于20,改写为Q对象如下:

          from django.db.models import Q

          list=BookInfo.objects.filter(Q(bread__gt=20))

        Q对象可以使用&,|连接,&表示逻辑与,|表示逻辑或。

        例如:查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现。

          list=BookInfo.objects.filter(Q(bread__gt=20) | Q(id__lt=3))

        Q对象前可以使用~操作符,表示非not。

        例如:查询编号不等于3的图书

          list=BookInfo.objects.filter(~Q(id=3))

      4.5 聚合函数

        使用aggregate()过滤器调用聚合函数。

        聚合函数包括:Avg、Count、Max、Min、Sum,被定义在django.db.models中。

        例如:查询图书的总阅读量

        from django.db.models import Sum

        list=BookInfo.objects.aggregate(Sum('bread'))

        注意aggregate的返回值是一个字典类型,格式为:

          {‘聚合类小写__属性名’:值}

          如:{'sum_bread':3}

        使用count时一般不使用aggregate()过滤器。

        例如:查询图书总数

          list=BookInfo.objects.count()

        注意:count函数的返回值是一个数字。

    5、查询集

      查询集表示从数据库中获取的对象集合,在管理器objects上调用某些过滤器方法会返回查询集,查询集可以含有零个、一个或多个过滤器。

      过滤器基于所给的参数限制查询的结果,从SQL的角度,查询集和select语句等价,过滤器像where和limit子句。

      5.1 返回查询集的过滤器

        (1)all():返回所有数据

        (2)filter():返回满足条件的数据

        (3)exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字

        (4)order_by():对结果进行排序

      5.2 返回单个值的过滤器

        (1)get():返回单个满足条件的对象

            1)如果未找到会引发“模型类.DoesNotExist”异常

            2)如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常

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

        (3)aggregate():聚合,返回一个字典

      5.3 判断某一个查询集中是否有数据

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

      5.4 两大特性

        (1)惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用。

        (2)缓存:使用同一个查询集,第一次使用时会发生数据库的查询,然后把结果缓存下来,再次使用这个查询集时会使用缓存的数据。

      5.5 查询集的缓存

        每个查询集都包含一个缓存来最小化对数据库的访问,在新建的查询集中,缓存为空,首次对查询集求值时,会发生数据库查询,django会将查询的结果存在查询集的缓存中,并返回请求的结果,接下来对查询集求值将重用缓存中的结果。

      5.6 限制查询集

        可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句,切片时不支持负数索引。

        对查询集进行切片后返回一个新的查询集,不会立即执行查询。

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

        例如:获取第1、2项

          list=BookInfo.objects.all()[0:2]

    6、模型类关系

      6.1 关系字段类型

        关系型数据库的关系包括三种类型:

        (1)ForeignKey:一对多,将字段定义在多的一端中。

        (2)MangToManyField:多对多,将字段定义在任意一端中。

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

        (4)可以维护递归的关联关系,使用'self'指定,即自关联。

      6.2 关联查询

        6.2.1 通过对象执行关联查询

          由一到多的访问语法:一对应的模型类对象.多对应的模型类名小写_set

          例如:b = BookInfo.objects.get(id=1)

             b.heroinfo_set.all()

          由多到一的访问语法:多对应的模型类对象.多对应的模型类中的关系类属性名

          例如:h=HeroInfo.objects.get(id=1)

             h.hbook

          访问一对应的模型类关联对象的id语法:多对应的模型类对象.关联类属性_id

          例如:h=HeroInfo.objects.get(id=1)

             h.hbook_id

        6.2.2 通过模型类执行关联查询

          由多模型类条件查询一模型类数据

          语法:关联模型类名小写__属性名__条件运算符=值

          当没有"__运算符"部分,表示等于,结果和sql中的inner join相同。

          例如:查询图书,要求图书中英雄的描述包含“八”

            list=BookInfo.objects.filter(heroinfo__hcomment__contains="八")

          由一模型类条件查询多模型类数据

          语法:一模型类关联属性名__一模型类属性名__条件运算符=值

          例如:查询书名为“天龙八部”的所有英雄

            list=HeroInfo.objects.filter(hbook_btitle="天龙八部")

      6.3 自关联

        对于地区信息、分类信息等数据,表结构非常类似,每个表的数据量十分有限,为了充分利用数据表的大量数据存储功能,可以设计成一张表,内部的关系字段指向本表的主键,这就是自关联的表结构。

        说明:关系属性使用self指向本类,要求null和blank允许为空,因为一级数据是没有父级的。

    #定义地区模型类,存储省、市、区县信息
    class AreaInfo(models.Model):
        atitle=models.CharField(max_length=30)#名称
        aParent=models.ForeignKey('self',null=True,blank=True)#关系   

    7、模型类扩展

      7.1 模型实例方法

        (1)str():在将对象转换成字符串时会被调用。

        (2)save():将模型对象保存到数据表中,ORM框架会转换成对应的insert或update语句。

        (3)delete():将模型对象从数据表中删除,ORM框架会转换成对应的delete语句。

      7.2 模型类的属性

        属性objects:管理器,是models.Manager类型的对象,用于与数据库进行交互。

        当没有为模型类定义管理器时,Django会为每一个模型类生成一个名为objects的管理器,自定义管理器后,Django不再生成默认管理器objects。

        为模型类BookInfo定义管理器books语法如下:

          class BookInfo(models.Model):

            ...

            books=models.Manager()

      7.3 管理器Manager

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

        Django支持自定义管理器类,继承自models.Manager。

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

        (1)修改原始查询集,重写all()方法

        (2)向管理器类中添加额外的方法,如向数据库中插入数据。

        7.3.1 修改原始查询集,重写all()方法

          (1)定义类BookInfoManager    

    #图书管理器
    class BookInfoManager(models.Manager):
        def all(self):
            #默认查询未删除的图书信息
            #调用父类的成员语法为:super().方法名
            return super().all().filter(isDelete=False)

          (2)在模型类BookInfo中定义管理器    

    class BookInfo(models.Model):
        ...
        books = BookInfoManager()

        7.3.2 在管理器类中定义创建对象的方法

          对模型类对应的数据表进行操作时,推荐将这些操作数据表的方法封装起来,放到模型管理器类中。

          (1)定义方法create

    class BookInfoManager(models.Manager):
        ...
        #创建模型类,接收参数为属性赋值
        def create_book(self, title, pub_date):
            #创建模型类对象self.model可以获得模型类
            book = self.model()
            book.btitle = title
            book.bpub_date = pub_date
            book.bread=0
            book.bcommet=0
            book.isDelete = False
            # 将数据插入进数据表
            book.save()
            return book

          (2)为模型类BookInfo定义管理器books语法

    class BookInfo(models.Model):
        ...
        books = BookInfoManager()

          (3)调用语法 

    调用:book=BookInfo.books.create_book("abc",date(1980,1,1))

      7.4 元选项

        在模型类中定义类Meta,用于设置元信息,如使用db_table自定义表的名字。

        数据表的默认名称为:

          <app_name>_<model_name>,例如:booktest_bookinfo

        指定BookInfo模型类生成的数据表名为bookinfo

        在BookInfo模型类中添加如下内容:

    #定义图书模型类BookInfo
    class BookInfo(models.Model):
        ...
    
        #定义元选项
        class Meta:
          db_table='bookinfo' #指定BookInfo生成的数据表名为bookinfo

      

      

          

  • 相关阅读:
    毕设进度2020.02.06
    毕设进度2020.02.05
    毕设进度2020.02.04
    学习进度2020.02.03
    学习进度2020.02.02
    学习进度2020.02.01
    毕设之路:本周计划(五)2019.11.18——2019.11.23
    毕设之路:本周计划(四)2019.11.11——2019.11.17
    洛谷P2015 二叉苹果树
    洛谷P1131 [ZJOI2007]时态同步
  • 原文地址:https://www.cnblogs.com/nuochengze/p/12747804.html
Copyright © 2011-2022 走看看