• Django入门学习--模型与数据库(models)


      Django对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite和Oracle,而且为这些数据库提供了统一的调用API,这些API统称为ORM框架。通过使用Django内置的ORM框架可以实现数据库连接和读写操作。

    构建模型

    ORM框架是一种程序技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。从效果上说,其实是创建了一个可在编程语言中使用的“虚拟对象数据库”,通过对虚拟对象数据库操作从而实现对目标数据库的操作,虚拟对象数据库与目标数据库是相互对应的。在Django中,虚拟对象数据库也称为模型。通过模型实现对目标数据库的读写操作,实现方法如下:

    配置目标数据库信息

    # __init__.py 中添加
     import pymysql
     pymysql.install_as_MySQLdb()
    
    # 点击保存连接,进入到base.py 注释掉base.py 中的
    #if version < (1, 3, 13):
    #    raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
    
    DATABASES = {
        # 'default': {
        #     'ENGINE': 'django.db.backends.sqlite3',
        #     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        # },
        # mysql 的配置
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'django_database',  # 你的数据库名
            'USER': 'root',  			# 你的用户
            'PASSWORD':'abcdef' , 		# 你的密码
            'HOST': '192.168.43.205' , 	# 数据库所在IP, 
            'PORT': '3306' , 			# 端口
        }
    }
    

    如果数据库不能远程,可参考mysql远程访问中的mysql命令改表法,能快速实现。

    构建虚拟数据库

    from django.db import models
    
    # Create your models here.
    
    
    class Type(models.Model):
        id = models.IntegerField(primary_key=True)
        type_name = models.CharField(max_length=20)
    
    
    class Product(models.Model):
        id = models.IntegerField(primary_key=True)
        name = models.CharField(max_length=50)
        weight = models.CharField(max_length=20)
        size = models.CharField(max_length=100)
        type = models.ForeignKey(Type, on_delete=models.CASCADE)
        
    

    在上述例子中,我们创建了数据表index_product和index_type,而表字段是在模型中定义的,在模型Type和Product中定义的字段类型有整型和字符串类型,但在实际开发中,我们需要定义不同的数据类型来满足各种需求,因此Django划分了多种不同的数据类型:
    image.png
    Django提供的字段类型还会对数据进行正则处理和验证功能等,进一步完善了数据的严谨性。除了表字段类型之外,每个表字段还可以设置相应的参数,使得表字段更加完善。
    image.png

    虚拟数据库迁移到目标数据库

    python manage.py makemigrations
    
    python manage.py migrate
    

    makemigrations指令用于将index所定义的模型生成0001_initial.py文件,该文件存放在index的migrations文件夹,打开查看0001_initial.py文件。
    image.png

    image.png

    数据表间的关系

    一个模型对应目标数据库的一个数据表,但我们知道,每个数据表之间是可以存在关联的,表与表之间有三种关系:一对一、一对多和多对多。

    一对一关系

    在模型中可以通过OneToOneField来构建数据表的一对一关系,代码如下:

    class Performer(models.Model):
        id = models.IntegerField(primary_key=True)
        name = models.CharField(max_length=20)
        nationality = models.CharField(max_length=20)
        masterprice = models.CharField(max_length=50)
    
    
    class Performer_Info(models.Model):
        id = models.IntegerField(primary_key=True)
        performer = models.OneToOneField(Performer, on_delete=models.CASCADE) #一对一
        birth = models.CharField(max_length=20)
        elapse = models.CharField(max_length=20)
    

    一对多关系

    在模型中可以通过ForeignKey来构建数据表的一对多关系,代码如下:

    class Program(models.Model):
        id = models.IntegerField(primary_key=True)
        performer = models.ForeignKey(Performer,on_delete=models.CASCADE)
        name = models.CharField(max_length=20)
    

    多对的关系

    在模型中可以通过ManyToManyField来构建数据表多的对多关系,代码如下:

    class Advertiser(models.Model):
        id = models.IntegerField(primary_key=True)
        name = models.CharField(max_length=20)
        performer = models.ManyToManyField(Performer)
    

    进行数据迁移:

    python manage.py makemigrations
    
    python manage.py migrate
    

    image.png

    数据表的读写

    数据库的读写操作主要对数据进行增、删、改、查。以的数据表index_type和index_product为例,分别在两个数据表中添加下面的数据。
    image.png
    image.png
     为了更好地演示数据库的读写操作,在项目中使用shell模式(启动命令行和执行脚本)进行讲述,该模式主要为方便开发人员开发和调试程序。在PyCharm的Terminal下开启shell模式,输入python manage.py shell指令即可开启:
    image.png

    插入数据

    下面在index_type中插入数据

    from index.models import *
    t = Type(id=1,type_name='手机')
    t.save()
    t = Type(id=2,type_name='平板电脑')
    t.save()
    t = Type(id=3,type_name='智能穿戴')
    t.save()
    t = Type(id=4,type_name='通用配件')
    t.save()
    
    p = Product(id=1,name='荣耀V10',weight='172g',size='157.00*74.98*6.97mm',type_id=1)
    p.save()
    p = Product(id=2,name='HuaWEI nova2s',weight='169g',size='156.9*75.1*7.5mm',type_id=1)
    p.save()
    p = Product(id=3,name='荣耀Waterplay',weight='465g',size='248*173*7.8mm',type_id=2)
    p.save()
    p = Product(id=4,name='荣耀畅玩平板',weight='460g',size='9.8*159.8*7.95mm',type_id=2)
    p.save()
    p = Product(id=5,name='PORSCHE DESIGN',weight='64g',size='45*48.3*1.6mm',type_id=3)
    p.save()
    p = Product(id=6,name='华为运动手环',weight='21g',size='44*19.7*10.3mm',type_id=3)
    p.save()
    p = Product(id=7,name='荣耀移动电源1000mA',weight='210g',size='139*73.7*15.5mm',type_id=4)
    p.save()
    p = Product(id=8,name='荣耀体脂秤',weight='1850g',size='300*300*23.7mm',type_id=4)
    p.save()
    

    更新数据

    image.png

    删除数据

    image.png

    查询数据

    from index.models import *
    #------ 全表查询 ------------
    # SQL:select * from index_product,
    p = Product.objects.all()
    p[1].name
    
    #SQL: select * from index_product LIMIT 5,
    p = Product.objects.all()[:5]
    
    #SQL: select name from index_product,
    p = Product.objects.values('name')
    
    #------where 查询 ------------
    #SQL: select * from index_product where id = 2,
    p = Product.objects.get(id=2)
    p.name
    
    p = Product.objects.filter(id=2)
    p[0].name
    
    #------ and 查询 -----------
    #SQL: select * from index_product where id = 9 and name='华为荣耀',
    p = Product.objects.filter(name='华为荣耀',id=9)
    
    #------ or 查询 -----------
    #SQL: select * from index_product where id = 9 or name='华为荣耀',
    from django.db.models import Q
    p = Product.objects.filter(Q(name='华为荣耀')|Q(id=9))
    
    # ------ count() ---------
    #SQL:使用count方法统计查询数据的数据量
    p = Product.objects.filter(name='荣耀V10').count
    p 
    #------ distinct ------
    # SQL: select distinct name from index_product where name ='荣耀V10'
    p = Product.objects.values('name').filter(name='荣耀V10').distinct()
    p
    
    #------- order_by --------
    # SQL: select id, name from index_product order by id,
    p = Product.objects.order_by('-id','name')
    
    #------- group by -------
    select name, Sum(id) as 'id_sum' from index_product group by name order by null
    from django.db.models import Sum, Count
    p = Product.objects.values('name').annotate(Sum('id'))
    print(p.query)
    
    # ------ count() ---------
    # select Count(id) as 'id_count' from index_product
    p = Product.objects.aggregate(id_count=Count('id'))
    

    image.png

    多表查询

    我们了解到数据表的读写操作,但仅仅局限在单个数据表的操作。在日常的开发中,常常需要对多个数据表同时进行数据查询。多个数据表查询需要数据表之间建立了表关系才得以实现。
    一对多或一对一的表关系是通过外键实现关联的,而多表查询分为正向查询和反向查询。以模型Product和Type为例:
    • 如果查询对象的主体是模型Type,要查询模型Type的数据,那么该查询称为正向查询。
    • 如果查询对象的主体是模型Type,要通过模型Type查询模型Product的数据,那么该查询称为反向查询。
    image.png
    从上面的代码分析,因为正向查询的查询对象主体和查询的数据都来自于模型Type,因此正向查询在数据库中只执行了一次SQL查询。而反向查询通过t[0].product_set.values('name')来获取模型Product的数据,因此反向查询执行了两次SQL查询,首先查询模型Type的数据,然后根据第一次查询的结果再查询与模型Product相互关联的数据。为了减少反向查询的查询次数,我们可以使用select_related方法实现,该方法只执行一次SQL查询就能达到反向查询的效果。select_related使用方法如下:
    image.png

    p = Product.objects.select_related('type').values('name','type_type_name')
    print(p.query)
    

    image.png

    p = Product.objects.select_related('type').all()
    print(p.query)
    

    image.png

    p = Product.objects.select_related('type').filter(id_gt=8)
    print(p.query)
    

    image.png

    p = Product.objects.select_related('type').filter(type_type_name='手机').all()
    p
    



    参考文献:玩转Django 2.0/黄永祥著.-北京:清华大学出版社,2018

  • 相关阅读:
    php && 逻辑与运算符使用说明
    php无穷递归算法
    PHP foreach 用法
    centos安装g++
    php 编译中apxs
    shutdown()
    C语言strtok()函数:字符串分割
    细谈select函数(C语言)
    setsockopt的作用
    STL之七:STL各种容器的使用时机详解
  • 原文地址:https://www.cnblogs.com/sinlearn/p/12865286.html
Copyright © 2020-2023  润新知