zoukankan      html  css  js  c++  java
  • Django Web应用开发实战第七章

    一、ORM框架

      Django对各种数据库提供了很好的支持,包括PostgreSQL、MySQL、SQLite和Oracle,且为这些数据库提供了统一API方法,这些API统称为ORM框架。

      通过Django内置的ORM框架可以实现数据库连接和读写操作。

    二、模型定义与数据迁移

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

    • AutoField: 自增长类型,数据表的字段类型为整数,长度为11位
    • BigAutoField: 自增长类型,数据表的字段类型为bigint,长度为20位
    • CharField: 字符类型
    • BooleanField: 布尔类型
    • CommonSeparateIntegerField: 用逗号分割的整数类型
    • DateField: 日期(Date)类型
    • DatetimeField: 日期时间(Datetime)类型
    • Decimal: 十进制小数类型
    • EmailField: 字符类型,存储邮箱格式的字符串
    • FloatField: 浮点数类型,数据表的字段类型变成Double类型
    • IntegerField: 整数类型,数据表的字段类型为11位的整数
    • BigIntegerField: 长整数类型
    • IPAddressField: 字符类型,存储Ipv4地址的字符串
    • GenericIPAddressField: 字符类型,存储Ipv4和Ipv6地址的字符串
    • NullBooleanField: 允许为空的布尔类型
    • PositiveIntegerField: 正整数的整数类型
    • PositiveSmallIntegerField: 小正整数类型,取值范围0~32767
    • SlugField: 字符类型,包含字母、数字、下划线和连字符的字符串
    • TextField: 长文本类型
    • TimeField: 时间类型,显示时分秒HH:MM[:ss[.uuuuuuu]]
    • URLField: 字符类型,存储路由格式的字符串
    • BinaryField: 二进制数据类型
    • FileField: 字符类型,存储文件路径的字符串
    • ImageField: 字符类型,存储图片路径的字符串
    • FilePathField: 字符类型,从特定的文件目录选择某个文件
    允许设置的参数

    源码Field(django/db/models/fields/init.py)

    • verbose_name: 默认None,在Admin站点管理设置字符的显示名称
    • primary_key: 默认为False,若为True,则将字段设置成主键
    • max_length: 默认为None,设置字段的最大长度
    • unique: 默认为False,若为True,则设置字段的唯一属性
    • blank: 默认为False, 若为True,则设置字段允许为空值,数据库将存储空字符串
    • null: 默认为False,若为True,则字段允许为空值,数据库表现为NULL
    • db_index: 默认为False,若为True,则以此字段来创建数据库索引
    • default: 默认为NOT_PROVIDEDD对象,设置字段的默认值
    • editable: 默认为True,允许字段可编辑,用于设置Admin的新增数据的字段
    • serialize: 默认为True,允许字段序列化,可将数据转化为JSON格式
    • unique_for_date: 默认为None,设置日期字段的唯一性
    • unique_for_month: 默认为None,设置月份字段的唯一性
    • unique_for_year: 默认为None,设置年份字段的唯一性
    • choices: 默认空列表,设置字段的可选值
    • help_text: 默认为空字符串,用于设置表单的提示信息
    • db_column: 默认为None,设置数据表的列名称,若不设置,则字段名作为列名
    • db_tablespace: 默认为None,如果字段已创建索引,那么数据库的表空间名称将作为该字段的索引名称。注意:部分数据库不支持表空间
    • auto_created: 默认为False,若为True,则自动创建字段,用于一对一的关系模型
    • validators: 默认为空列表,设置字段内容的验证函数
    • error_message: 默认为None,设置错误提示
    • 以上参数适用于所有字段

    • 以下适用于Meta
    • abstract: 若设置为True,则该模型为抽象模型,不会在数据库里创建数据表
    • app_label:属性值为字符串,将模型设置为指定的项目应用,比如将index的models.py定义的模型A指定到其他的APP里
    • db_table: 属性值为字符串,设置模型所使用的数据库的表名
    • db_tablespace: 属性值为字符串,设置模型所使用的数据库的表名
    • get_lastest_by: 属性值为字符串或列表,设置模型数据的排序方式
    • managed: 默认为True,支持Django命令执行数据迁移;若为False,则不支持数据迁移功能
    • order_with_respect_to: 属性值为字符串,用于多对多的模型关系,指向某个关系模型的名称,并且模型名称必须为英文小写。若A模型对B模型一对多,两个模型关联后,当查询模型A的某条数据时,可使用get_b_order()和set_b_order()来获取B的关联数据;可使用get_next_in_order()和get_previous_in_order()获取当前数据的上一条和下一条数据
    • ordering: 属性值为列表,将模型数据以某个字段进行排序
    • permissions: 属性值为元组,设置模型的访问权限,默认设置添加、修改和删除的权限
    • proxy:若设置为True,则为模型创建代理模型,即为模块A克隆一个相同的模型B
    • required_db_features:属性值为列表,声明模型依赖的数据库功能,如['gis_enabled'],表示模型依赖GIS功能
    • required_db_vendor: 属性值为列表,声明模型依赖的数据库,默认支持SQLite、PostgreSQL、MySQL和Oracle
    • select_on_save: 数据新增修改算法,通常无需设置,默认为False
    • indexes: 属性值为列表,定义数据库表的索引列表
    • verbos_name: 属性值为字符串,设置模型直观可读的名称并以复数形式表示
    • verbos_name_plural: 与verbos_name相同,以单数形式表示
    • label: 只读属性,属性值为app_label.object_name
    • label_lower: 与label相同,但其值为字母小写
    导数据
    # 导出项目所有数据表
    python manage.py dumpdata > data.json
    
    # 导出某个项目名称所有模型
    python manage.py dumpdata index > data.json
    
    # 导出某个项目某个模型名称
    python manage.py dumpdata index.PersonInfo > data.json
    
    # 导入数据
    python manage.py loaddata data.json

    三、数据表关系

    # OneToOneField、ForeignKey、ManyToManyField
    # 参数
    - to: 必选参数,关联的模型名称
    - on_delete: 必选参数,设置数据删除模式,删除模型包括:CASCADE/PROTECT/SET_NULL/SET_DEFAULT/SET/DO_NOTHING
    - limit_choices_to: 设置外键的下拉选项,用于模型与表单和Admin后台系统
    - related_name: 用于模型之间的关联查询,如反向查询
    - related_query_name: 设置模型的查询名称,用于filter或get查询,若设置参数related_name则以该参数为默认值,若没有设置,则以模型名称的小写为默认值
    - to_field: 设置外键与其他模型字段的关联性,默认关联主键,若要关联其他字段,则该字段必须具有唯一性
    - db_constraint: 在数据库里是否创建外键约束,默认为true
    - swappable: 设置关联模型的替换功能,默认为true,比如模型A关联模型B,想让模型C继承并替换B使得A与模型C之间关联
    - symmetrical: 仅限于ManyToManyField,设置多对多字段之间的对称模式
    - through: 仅限于ManyToManyField,设置自定义模型C,用于管理和创建模型A和B否多对多关系
    - through_fields: 仅限于ManyToManyField,设置模型C的字段,确认模型C的哪些字段用于管理A和B否多对多关系
    - db_table: 仅限于ManyToManyField,为管理和存储多对多关系的数据表设置表名称

    四、数据查询

    去重distinct

    # 去重查询,distinct无需设置参数,去重方式根据values设置的字段执行
    # SQL: select * from index_vocation where job='123';
    v = Vocation.objects.values('job').filter(job='123').distinct()

    聚合查询annotate、aggregate

    # annotate类似sql里面的group by
    # 如果不设置values,默认对主键进行group by分组
    # SQL: select job, sum(id) as 'id__sum' from index_vocation group by job;
    v = Vocation.objects.annotate(Sum('id'))
    
    # aggregate是计算某个字段的值并返回计算结果
    # SQL: select count(id) as 'id__count' from index_vocation
    v = Vocation.objects.aggregate(id_count=Count('id'))

    结果集union、intersection、difference

    # 每次查询的字段必须一致
    v1 = Vocation.objects.filter(payment__gt=9000)
    v2 = Vocation.objects.filter(payment__gt=5000)
    
    # 使用SQL UNION来组合两个或多个查询结果的并集
    v1.union(v2)
    
    # 使用SQL INTERSECT来获取两个或多个查询结果的交集
    v1.intersection(v2)
    
    # 使用SQL EXCEPT来获取两个或多个查询结果的差集
    v2.difference(v2)

    查询条件get:查询字段必须是主键或者唯一约束的字段,且查询的数据必须存在,否则程序会抛异常

    查询条件filter:查询字段没有限制,只要该字段是数据表某一字即可。查询结果以列表形式返回,查询结果为空就返回空列表

    多表查询select_related、prefetch_related

    # select_related参数为字符串格式(外键字段related_name), 使用left outer join方式查询两个数据表
    # 查询模型PersonInfo的name字段和模型Vocation的payment字段
    p = PersonInfo.objects.select_related('personinfo').values('name', 'personinfo__payment')
    
    # select_related使用SQL的join实现的,对于多对多会增加数据查询时间和内存占用;prefetch_related更有优势
    # 查询模型Program的某行数据
    p = Program.objects.prefetch_related('performer').filter(name='123').first()
    # 根据外键字段proformer获取当前数据的多对多或一对多关系
    p.performer.all()

    执行sql

    # extra: 结果集修改器,一种提供额外查询参数的机制
    # 查询job=123的数据
    v = Vocation.objects.extra(where=['job=%s'], params=['123'])
    
    # 新增查询字段seat, select_params为selec的%s提供参数
    v = Vocation.objects.extra(select={'seat': '%s'}, select_params=['seatInfo'])
    
    # raw
    v = Vocation.objects.raw('select * from index_vocation')
    v[0]
    
    # execute很容易受到sql注入攻击
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute('select * from index_vocation')
    # 读取第一行数据
    cursor.fetchone()
    # 读取所有数据
    cursor.fetchall()

    迁移到不同数据库

    # 在default数据库中创建数据表
    python manage.py migrate
    
    # 在db1中创建数据表
    python manage.py migrate --database=db1

    五、数据库事务

    事物是指作为单个逻辑执行的一系列操作,这些操作具有原子性,即这些操作要么完全执行,要么完全不执行。
    事物处理可以确保事务性单元内所有操作都成功完成,否则不会执行数据操作。
    事物四大特性ACID:
    - 原子性(Atomicity):一个事物是一个不可分割的工作单位,事物中包括的操作要么都做,要么都不做。
    - 一致性(Consistency):事物必须使数据库从某个一致性状态到另一个一致性状态,一致性与原子性是密切相关的。
    - 隔离性:一个事物的执行不能被其他事物干扰,即一个事物内部的操作及使用的数据对其他事物是隔离的,各个事物之间互不干扰。
    - 持久性:也称永久性(Permanence),指一个事物一旦提交,它对数据库中数据的改变应该是永久性的,其他操作或故障不应该对其有任何影响。
    
    # Django事物定义在django/db/transaction.py
    - atomic(): 在视图函数或视图类使用事物
    - savepoint(): 开启事物
    - savepoint_rollback(): 回滚事物
    - savepoint_save(): 提交事物
    from django.shortcuts import render
    from .models import *
    from django.db import transaction
    from django.db.models import F
    
    @transaction.atomic
    def index(request):
        # 开启事物保护
        sid = transaction.savepoint()
        try:
            id = request.GET.get('id', '')
            if id:
                v = Vocation.objects.filter(id=id)
                v.update(payment=F('payment') + 1)
                print('Done')
                # 提交事物
                # 如不设置,当程序执行完成后,会自动提交事物
                # transaction.savepoint_commit(sid)
            else:
                # 全表的payment字段自减1
                Vocation.objects.update(payment=F('payment') - 1)
                # 事物回滚,将全表payment字段自减1的操作撤回
                transaction.savepoint_rollback(sid)
        except Expection as e:
            transaction.savepoint_rollback(sid)
            
        return render(request, 'index.html', local()) 
        
    # 使用with模块实现
    with transaction.atmonic():
        pass

    六、发送邮件

    # 邮件配置信息
    EMAIL_USE_SSL = True  # Django与邮件服务器的连接方式是否设置ssl模式
    
    # 邮件服务器,如果是163,就改成smtp.163.com
    EMAIL_HOST = 'smtp.qq.com'  # 设置服务器类型,qq邮箱分为SMTP和POP3服务器
    
    # 邮件服务器端口
    EMAIL_PORT = 465  # 若使用SMTP服务器,则端口应为465或587
    
    # 发送邮件的账号
    EMAIL_HOST_USER = '4512125@qq.com'  # 账号必须开启POP3/SMTP服务
    
    # SMTP服务密码
    EMAIL_HOST_PASSWORD = 'SFSDDSFSVGSF'  # 授权码
    
    # 设置默认发送邮件的账号
    DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
    实践出真知~
  • 相关阅读:
    nullptr和NULL
    tmux用于恢复远程屏幕
    如何改变git的默认路径
    scp拷贝文件
    C++头文件<bits/stdc++.h>
    MAME模拟器使用简单教程
    typescript接口扩展
    Typescript中的可索引接口 类类型接口
    typescript函数类型接口
    typescript静态属性 静态方法 抽象类 多态
  • 原文地址:https://www.cnblogs.com/NolaLi/p/14392173.html
Copyright © 2011-2022 走看看