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
    实践出真知~
  • 相关阅读:
    windows的80端口被占用时的处理方法
    Ansible自动化运维工具安装与使用实例
    Tomcat的测试网页换成自己项目首页
    LeetCode 219. Contains Duplicate II
    LeetCode Contest 177
    LeetCode 217. Contains Duplicate
    LeetCode 216. Combination Sum III(DFS)
    LeetCode 215. Kth Largest Element in an Array(排序)
    Contest 176 LeetCode 1354. Construct Target Array With Multiple Sums(优先队列,递推)
    Contest 176
  • 原文地址:https://www.cnblogs.com/NolaLi/p/14392173.html
Copyright © 2011-2022 走看看