• Django——模板层、模型层


    模板层

    一. 模版语法

    {{  }}: 变量相关

    {%  %}: 逻辑相关

     

    1. 注释是代码的母亲

    {# ... #} 

     

    2. 基本数据类型传值

    1. int1 = 123
    2. float1 = 11.11
    3. str1 = '我也想奔现'
    4. bool1 = True
    5. list1 = ['小红', '姗姗', '花花', '茹茹']
    6. tuple1 = (111, 222, 333, 444)
    7. dict1 = {'username': 'jason', 'age': 18, 'info': '这个人有点意思'}
    8. set1 = {'晶晶', '洋洋', '嘤嘤'}
    9. # 基本数据类型都支持
    10. {{ int1 }}
    11. {{ float1 }}
    12. {{ str1 }}
    13. {{ bool1 }}
    14. {{ list1 }}
    15. {{ tuple1 }}
    16. {{ dict1 }}
    17. {{ set1 }}

    3. 函数和类传值

    1. def func():
    2. print('我被执行了')
    3. return '你的另一半在等你'
    4. class MyClass(object):
    5. def get_self(self):
    6. return 'self'
    7. @staticmethod
    8. def get_func():
    9. return 'func'
    10. @classmethod
    11. def get_class(cls):
    12. return 'cls'
    13. # 对象被展示到html页面上 就类似于执行了打印操作也会触发__str__方法
    14. def __str__(self):
    15. return 'cls'
    16. obj = MyClass()
    17. # 传递函数名会自动加括号调用 但是模版语法不支持给函数传额外的参数
    18. {{ func }}
    19. # 传类名的时候也会自动加括号调用(实例化)
    20. {{ MyClass }}
    21. # 内部能够自动判断出当前的变量名是否可以加括号调用 如果可以就会自动执行 针对的是函数名和类名
    22. {{ obj }}
    23. {{ obj.get_self }}
    24. {{ obj.get_func }}
    25. {{ obj.get_class }}
    26. # 总结
    27. '''
    28. 1. 如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。
    29. 2. 如果使用的变量不存在, 它被默认设置为'' (空字符串) 。
    30. '''

    4. 模版语法的取值

    django模版语法的取值 是固定的格式 只能采用“句点符”

    1. {{ dict1.username }}
    2. {{ list1.0 }}

    3. {{ dict1.hobby3.info }}

    5. 模板语法的优先级

    .在模板语言中有特殊的含义。当模版系统遇到点.,它将以这样的顺序查询:

    1. '''
    2. 1. 字典查询(Dictionary lookup)
    3. 2. 属性或方法查询(Attribute or method lookup)
    4. 3. 数字索引查询(Numeric index lookup)
    5. '''

    二. Filters过滤器(注意: 过滤器只能最多有两个参数)

    过滤器就类似于是模版语法内置的 内置方法.

    django内置有60多个过滤器我们这里了解一部分即可

    过滤器语法: {{数据|过滤器:可选参数}}

    注意事项:

    1. '''
    2. 1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
    3. 2. 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
    4. 3. 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
    5. 4. '|'左右没有空格没有空格没有空格
    6. '''

     

    Django的模板语言中提供了大约六十个内置过滤器我们这里介绍14种:

    1. # 统计长度: 作用于字符串和列表。
    2. {{ str1|length }}
    3. # 默认值: 第一个参数布尔值是True就展示第一个参数的值否则就展示冒号后面的值
    4. {{ bool1|default:'谁的布尔值为True谁就展示' }}
    5. # 文件大小:
    6. {{ file_size|filesizeformat }} # 9.8 KB
    7. # 日期格式化: 将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等
    8. {{ current_time|date }} # May 29, 2020
    9. {{ current_time|date:'Y-m-d' }} # 2020-05-29
    10. {{ current_time|date:'Y-m-d H:i:s' }} # 2020-05-29 01:31:09
    11. # 切片操作: 支持步长
    12. {{ list1|slice:'0:4:2' }}
    13. # 切取字符: 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾 (注意: 包含这三个点)
    14. {{ info|truncatechars:9 }}
    15. # 切取单词: 不包含三个点 按照空格切取, 不是识别单词语法
    16. {{ msg|truncatewords:3 }}
    17. # 移除特定的字符:
    18. {{ msg|cut:' '}}
    19. # 拼接操作:
    20. # join
    21. {{ info|join:'$' }}
    22. # 加法: 数字就相加 字符就拼接
    23. {{ int1|add:float1 }}
    24. {{ str1|add:str1 }}
    25. # 转义!!!!:
    26. # 后端的转义
    27. from django.utils.safestring import mark_safe
    28. html_safe = mark_safe('

      哈哈哈

      '
      )
    29. {{ html }} # 普通的标签使用模板, 任然是模板
    30. {{ html_safe }} # 后端的转义传值
    31. {{ html|safe }} # 前端的转义

    date参数介绍:

    格式化字符描述示例输出
    a'a.m.''p.m.'(请注意,这与PHP的输出略有不同,因为这包括符合Associated Press风格的期间)'a.m.'
    A'AM''PM''AM'
    b月,文字,3个字母,小写。'jan'
    B未实现。
    cISO 8601格式。 (注意:与其他格式化程序不同,例如“Z”,“O”或“r”,如果值为naive datetime,则“c”格式化程序不会添加时区偏移量(请参阅datetime.tzinfo) 。2008-01-02T10:30:00.000123+02:002008-01-02T10:30:00.000123如果datetime是天真的
    d月的日子,带前导零的2位数字。'01''31'
    D一周中的文字,3个字母。“星期五”
    e时区名称 可能是任何格式,或者可能返回一个空字符串,具体取决于datetime。'''GMT''-500''US/Eastern'
    E月份,特定地区的替代表示通常用于长日期表示。'listopada'(对于波兰语区域,而不是'Listopad'
    f时间,在12小时的小时和分钟内,如果它们为零,则分钟停留。 专有扩展。'1''1:30'
    F月,文,长。'一月'
    g小时,12小时格式,无前导零。'1''12'
    G小时,24小时格式,无前导零。'0''23'
    h小时,12小时格式。'01''12'
    H小时,24小时格式。'00''23'
    i分钟。'00''59'
    I夏令时间,无论是否生效。'1''0'
    j没有前导零的月份的日子。'1''31'
    l星期几,文字长。'星期五'
    L布尔值是否是一个闰年。TrueFalse
    m月,2位数字带前导零。'01''12'
    M月,文字,3个字母。“扬”
    n月无前导零。'1''12'
    N美联社风格的月份缩写。 专有扩展。'Jan.''Feb.''March''May'
    oISO-8601周编号,对应于使用闰年的ISO-8601周数(W)。 对于更常见的年份格式,请参见Y。'1999年'
    O与格林威治时间的差异在几小时内。'+0200'
    P时间为12小时,分钟和'a.m。'/'p.m。',如果为零,分钟停留,特殊情况下的字符串“午夜”和“中午”。 专有扩展。'1 am''1:30 pm' / t3>,'midnight','noon','12:30 pm' / T10>
    rRFC 5322格式化日期。'Thu, 21 Dec 2000 16:01:07 +0200'
    s秒,带前导零的2位数字。'00''59'
    S一个月的英文序数后缀,2个字符。'st''nd''rd''th'
    t给定月份的天数。28 to 31
    T本机的时区。'EST''MDT'
    u微秒。000000 to 999999
    U自Unix Epoch以来的二分之一(1970年1月1日00:00:00 UTC)。
    w星期几,数字无前导零。'0'(星期日)至'6'(星期六)
    WISO-8601周数,周数从星期一开始。153
    y年份,2位数字。'99'
    Y年,4位数。'1999年'
    z一年中的日子0365
    Z时区偏移量,单位为秒。 UTC以西时区的偏移量总是为负数,对于UTC以东时,它们总是为正。-4320043200

    三. 标签

    1. for循环

    forloop.first第一次循环返回True, 其余返回False
    forloop.last最后一次循环返回False, 其余返回True
    forloop.counter当前循环次数. 从1开始
    forloop.counter0当前循环索引. 从0开始
    forloop.revcounter当前循环次数取反
    forloop.revcounter0当前循环索引取反
    forloop.parentloop本层循环的外层循环

    展示格式:

    1. {'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
    2. {'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False}
    3. {'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False}
    4. {'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True}
    1. {% for foo in list1 %}
    2. {{ forloop }}

    3. {{ foo }}

      # 一个个元素
    4. {% endfor %}

    2. if判断

    1. # if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断
    2. {% if bool1 %}
    3. 1111

    4. {% elif int1 %}
    5. 2222

    6. {% else %}
    7. 3333

    8. {% endif %}

    3. for与if混合使用

    1. {% for foo in list1 %}
    2. {% if forloop.first %}
    3. 这是我的第一次

    4. {% elif forloop.last %}
    5. 这是最后一次啊

    6. {% else %}
    7. 上面都不是才轮到我

    8. {% endif %}
    9. {% empty %}
    10. for循环的可迭代对象内部没有元素 根本没法循环

    11. {% endfor %}

    4. 处理字典values,keys,items方法

    1. {% for foo in dict1.values %}
    2. {{foo}}

    3. {% endfor %}
    4. {% for foo in dict1.keys %}
    5. {{foo}}

    6. {% endfor %}
    7. {% for foo in dict1.items %}
    8. {{foo}}

    9. {% endfor %}

    5. with起别名

    在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式

    1. dict1 = {'username': 'egon', 'hobby': ['吃', '喝', '玩', {'info': '他喜欢吃生蚝!!!'}]}
    2. # 书写方式一: as语句
    3. {% with dict1.hobby.3.info as nb %}
    4. {{ nb }}

    5. {# 与上面等同, 但是长语句, 还是使用with赋值来进行 #}
    6. {{ dict1.hobby.3.info }}

    7. {% endwith %}
    8. # 书写方式二: 赋值
    9. {% with nb=dict1.hobby.3.info %}
    10. {{ nb }}

    11. {# 与上面等同, 但是长语句, 还是使用with赋值来进行 #}
    12. {{ dict1.hobby.3.info }}

    13. {% endwith %}

    四. 自定义过滤器、标签、inclusion_tag

    1. 准备步骤

    1. 1. 在应用下创建一个名字”必须“叫templatetags文件夹
    2. 2. 在该文件夹内创建“任意”名称的py文件
    3. 3. 在该py文件内"必须"先书写下面两句话(单词一个都不能错)
    4. from django import template
    5. register = template.Library()

     

    2. 自定义过滤器

    强调: 自定义过滤器函数, 最大只能设有2个形参

    1. from .templatetags.mytag import register
    2. @register.filter(name='my_sum')
    3. def abc(v1, v2): # abc函数名任意. 导入自定义过滤器使用的是上面指定的name的值
    4. return v1 + v2
    5. # 使用: (注意: 先导入我们自定义filter那个文件mytag)
    6. {% load mytag %}
    7. {{ int1|my_sum:100 }}

    3. 自定义标签

    1. # 自定义标签: 数可以有多个 类似于自定义函数
    2. from .templatetags.mytag import register
    3. @register.simple_tag(name='my_join')
    4. def abc(a, b, c, d): # abc函数名任意. 导入自定义标签使用的是上面指定的name的值
    5. return f'{a}-{b}-{c}-{d}'
    6. # 使用: 标签多个参数彼此之间空格隔开(注意: 先导入我们自定义filter那个文件mytag)
    7. {% load mytag %}
    8. p>{% my_join 'json' 123 123 123 %}

    4. 自定义inclusion_tag

    1. '''
    2. 内部原理:
    3. 先定义一个方法
    4. 在页面上调用该方法 并且可以传值
    5. 该方法会生成一些数据然后传递给一个html页面
    6. 之后将渲染好的结果放到调用的位置
    7. '''
    8. from .templatetags.mytag import register
    9. @register.inclusion_tag('left_memu.html') # 注意: 这里传的是渲染的HTML文件, 不需要指定关键字name
    10. def left(n):
    11. data = ['第{}项'.format(i) for i in range(n)]
    12. # 第一种: 将data传递给left_menu.html
    13. # return {'data':data}
    14. # 第二种: 将data传递给left_menu.html
    15. return locals()
    16. # left_memu.html
    17. {% for foo in data %}
    18. {% if forloop.first %}
    19. {{foo}}

    20. {% elif forloop.last %}
    21. {{ foo }}

    22. {% endif %}
    23. {% endfor %}
    24. # index使用(注意: 先导入我们自定义filter那个文件mytag)
    25. {% load mytag %}
    26. {% left 5 %}

     

    五. 模板的继承

    1. # 模版的继承 你自己先选好一个你要想继承的模版页面
    2. {% extends 'home.html' %}
    3. # 继承了之后子页面跟模版页面长的是一模一样的 你需要在模版页面上提前划定可以被修改的区域
    4. {% block content %}
    5. 模版内容
    6. {% endblock %}
    7. # 子页面就可以声明想要修改哪块划定了的区域
    8. {% block content %}
    9. 子页面内容
    10. {% endblock %}
    11. # 一般情况下模版页面上应该至少有三块可以被修改的区域, 这样每一个子页面就都可以有自己独有的css代码 html代码 js代码
    12. {% block css %}
    13. 1.css区域
    14. {% endblock %}
    15. {% block content %}
    16. 2.html区域
    17. {% endblock %}
    18. {% block js %}
    19. 3.js区域
    20. {% endblock %}
    21. """
    22. 一般情况下 模版的页面上划定的区域越多 那么该模版的扩展性就越高
    23. 但是如果太多 那还不如自己直接写
    24. """

    六. 模版的导入

    1. """
    2. 将页面的某一个局部当成模块的形式
    3. 哪个地方需要就可以直接导入使用即可
    4. """
    5. '''静态导入'''
    6. {% include 'wasai.html' %}
    7. '''动态导入'''
    8. # 被导入的text.html
    9. {{ name }}

      {# 这里的name就是"egon"#}
    10. # 导入html的文件
    11. {% include 'text.html' with name='"egon"' %}
    12. # 不过上面的导入的参数是写死的. 如果你想动态的通过模板语法传参, 你可以这样
    13. {% include 'text.html' with name=username %} {#注意哦! 这里的username是视图层传过来的哦!#}
    14. # 被导入文件中如果想{{ name }}模板以后是字符串的格式你可以这也指定即可!
    15. '{{ name }}'

      {#注意: 如果不加引号, 这种字符串的格式的话, 那么name模板传值以后就是一个变量.#}

    模型层

    一. 配置测试脚本

    当你只是想测试django中的某一个py文件内容 那么你可以不用书写前后端交互的形式, 而是直接写一个测试脚本即可:

    1. # 测试环境的准备 去manage.py中拷贝前四行代码 然后自己写两行
    2. import os
    3. if __name__ == "__main__":
    4. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")
    5. import django
    6. django.setup()
    7. # 在这个代码块的下面就可以测试django里面的单个py文件了(注意: 导模块也要写在这下面)

    二. ORM常用字段类型和参数

    1. 常用字段

    常用字段描述与MySQL字段对应关系
    AutoField必须指定参数primary_key=True指定主键. 如果没有设置主键, 默认创建并以id名作为主键integer auto_increment
    IntegerField整型字段. 存储宽度4Bytes. 无符号: 0~2^32 有符号: -232/2~232-1int 或 integer
    BigIntegerField整型字段. 存储宽度8Bytes. 无符号: 0~2^64 有符号: -264/2~264-1bigint
    DeciamlField浮点字段. 必须指定参数max_digits设置总长度. decimal_places设置小数位长度numeric(%(max_digits)s, %(decimal_places)s)
    EmailField字符字段. Django Admin以及ModelForm中提供验证机制
    CharField字符字段. 必须指定参数max_length参数设置字符存储个数. Django中的CharField对应的MySQL数据库中的varchar类型,没有设置对应char类型的字段,但是Django允许我们自定义新的字段.varchar(%(max_length)s)
    DateField日期字段. 格式: 年-月-日. 一般指定参数auto_now=Ture更新记录的时间, 或者auto_now_add=True插入记录的时间date
    DateTimeField日期字段. 格式: 年-月-日 时:分:秒 一般指定参数auto_now=Ture更新记录的时间, 或者auto_now_add=True插入记录的时间datetime

    2. 字段类型(联想记忆: 与MySQL字段对应关系)

    2-1. 自增长字段
    1. models.AutoField(primary_key=True) # 必须填入参数 primary_key=True
    2. models.BigAutoField(primary_key=True) # 必须填入参数 primary_key=True
    3. # 与MySQL字段对应关系
    4. 'AutoField': 'integer AUTO_INCREMENT',
    5. 'BigAutoField': 'bigint AUTO_INCREMENT',

     注:当model中如果没有自增列,则自动会创建一个列名为id的列

    2-2. 二进制字段
    1. models.BinaryField()
    2. # 与MySQL字段对应关系
    3. 'BinaryField': 'longblob',

    2-3. 布尔型字段
    1. models.BooleanField() # 该字段传布尔值(False/True) 数据库里面存0/1
    2. models.NullBooleanField()
    3. # 与MySQL字段对应关系
    4. 'BooleanField': 'bool',

    Django提供了两种布尔类型的字段,上面这种不能为空,下面这种的字段值可以为空。

    2-4. 整型字段
    掌握
    1. models.IntegerField() # 整数列(有符号的) -2147483648 ~ 2147483647
    2. models.BigIntegerField() # 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
    3. # 与MySQL字段对应关系
    4. 'IntegerField': 'integer',
    5. 'BigIntegerField': 'bigint',
    了解
    1. models.PositiveSmallIntegerField() # 正小整数 0 ~ 327672147483647
    2. models.PositiveIntegerField() # 正整数 0 ~ 2147483647
    3. models.SmallIntegerField() # 小整数 -32768 ~ 32767
    4. # 与MySQL字段对应关系
    5. 'PositiveIntegerField': 'integer UNSIGNED',
    6. 'PositiveSmallIntegerField': 'smallint UNSIGNED',
    7. 'SmallIntegerField': 'smallint',

    2-5. 字符串类型
    1. models.CharField(max_length) # 以varchar类型存储 注: 必须提供max_length参数, max_length表示字符长度
    2. models.TextField() # longtext 文本类型 该字段可以用来存大段内容(文章、博客...) 没有字数限制
    3. # 与MySQL字段对应关系
    4. 'CharField': 'varchar(%(max_length)s)'
    5. 'TextField': 'longtext',

     

    Django Admin以及ModelForm中提供:

    邮箱

    EmailField()                  # Django Admin以及ModelForm中提供验证机制.  以varchar(254)形式存储

    地址

    1. IPAddressField() # Django Admin以及ModelForm中提供验证 IPV4 机制
    2. GenericIPAddressField() # Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
    3. # 参数:
    4. protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
    5. unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both"
    6. # 与MySQL字段对应关系
    7. 'IPAddressField': 'char(15)',
    8. 'GenericIPAddressField': 'char(39)',

    URL

    URLField()                    # Django Admin以及ModelForm中提供验证 URL 

    文件

    1. FileField() # 给该字段传一个文件对象,会自动将文件保存到/data目录下然后将文件路径保存到数据库中 /data/a.txt
    2. # 参数:
    3. upload_to = "" 上传文件的保存路径
    4. storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
    5. FilePathField() # Django Admin以及ModelForm中提供读取文件夹下文件的功能
    6. # 参数:
    7. path, 文件夹路径
    8. match=None, 正则匹配
    9. recursive=False, 递归下面的文件夹
    10. allow_files=True, 允许文件
    11. allow_folders=False, 允许文件夹
    12. # 与MySQL字段对应关系
    13. 'FileField': 'varchar(%(max_length)s)',
    14. 'FilePathField': 'varchar(%(max_length)s)',

    图片

    1. ImageField() # 路径保存在数据库,文件上传到指定目录
    2. # 参数:
    3. upload_to = "" 上传文件的保存路径
    4. storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
    5. width_field=None, 上传图片的高度保存的数据库字段名(字符串)
    6. height_field=None 上传图片的宽度保存的数据库字段名(字符串)xxxxxxxxxx6 1ImageField() # 路径保存在数据库,文件上传到指定目录2 # 参数:3 upload_to = "" 上传文件的保存路径4 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage5 width_field=None, 上传图片的高度保存的数据库字段名(字符串)6 height_field=None 上传图片的宽度保存的数据库字段名(字符串)python

    其他

    1. SlugField() # Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
    2. CommaSeparatedIntegerField() # 格式必须为逗号分割的数字
    3. UUIDField() # Django Admin以及ModelForm中提供对UUID格式的验证
    4. # 与MySQL字段对应关系
    5. 'SlugField': 'varchar(%(max_length)s)',
    6. 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)'
    7. 'UUIDField': 'char(32)',

    2-6. 时间类型
    1. models.DateField() # 年-月-日
    2. models.DateTimeField() # 年-月-日 时:分:秒
    3. models.DurationField() # 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
    4. # 与MySQL字段对应关系
    5. 'DateField': 'date'
    6. 'TextField': 'longtext'
    7. 'DateTimeField': 'datetime'
    8. 'DurationField': 'bigint'

    2-7. 浮点型
    1. models.FloatField()
    2. models.DecimalField() # 10进制小数
    3. # 参数:
    4. max_digits,小数总长度
    5. decimal_places,小数位长度
    6. # 与MySQL字段对应关系
    7. 'FloatField': 'double precision'
    8. 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)'

    2-8. 关系型字段
    1. # 前提: 先建立基表 再建立外键关系 无序同mysql中操作需要考虑外键关系的创建以及记录的插入顺序
    2. # 一对多关系建表: 建立在多的一方
    3. publish = models.ForeignKey(to='Publish)
    4. # 多对多关系建表: 建立在查询频率高的一方
    5. 提示: 无序在mysql中操作需要建立中间表, models会默认帮你创建虚拟中间表表
    6. authors = models.ManToManyField(to='Book')
    7. # 一对一关系建表: 建立在查询频率高的一方
    8. author_detail = models.OneToOneField(to='AuthorDetail')
    9. # 补充: 建立一对多, 一对一关系的外键关联表, 关联表中默认会在建立的外键字段之后拼接_id, 我们无序指定.

    3. 字段参数

    3-1. 所有字段都具有的参数
    1. # 更改字段名
    2. db_colum=''
    3. # 设置主键
    4. primary_key=True,默认为False
    5. # 给字段设置别名(备注)
    6. verbose_name=''
    7. # 为字段设置默认值
    8. default
    9. # 字段的唯一键属性
    10. unique=True,设置之后,这个字段的没一条记录的每个值是唯一的
    11. # 允许字段为空
    12. null=True(数据库中字段可以为空),blank=True(网页表单提交内容可以为空),切记不可以将null设置为Fasle的同时还把blank设置为True。会报错的。
    13. # 给字段建立索引
    14. db_index=True
    15. # 在表单中显示说明
    16. help_text=''
    17. # 字段值不允许更改
    18. editable=False,默认是True,可以更改。

    3-2. 个别字段才有的参数
    1. # CharField(max_length=100)
    2. 字段长度为utf8编码的100个字符串
    3. # DateField(unique_for_date=True)
    4. 这个字段的时间必须唯一
    5. # DecimalField(max_digits=4, decimal_places=2)
    6. 前者表示整数和小数总共多少数,后者表示小数点的位数

     

    3-3. auto_now 和 auto_now_add 
    1. # 提示: 一般作为DateField和DateTimeField参数
    2. # auto_now=True
    3. 对这条记录内容更新的时间
    4. # auto_now_add=True
    5. 插入这条记录的时间

    3-4. 关系型字段的参数
    1. # to
    2. 设置要关联的表
    3. unique=True
    4. ForeignKey(unique=True) === OneToOneField()
    5. # 你在用前面字段创建一对一 orm会有一个提示信息 orm推荐你使用后者但是前者也能用
    6. # to_field
    7. 置要关联的表的字段 默认不写关联的就是另外一张的主键字段.
    8. # on_delete=models.CASECADE 和 on_update=models.CASECADE
    9. 设置级联更新级联删除. 同等与SQL语言中的ON DELETE CASCADE等约束 (提示: 该操作为Django1.X版本的默认操作, 2.X和3.X需要手动指定)
    10. # db_index
    11. 如果db_index=True 则代表着为此字段设置索引
    12. # db_constraint:
    13. 注意:db_constraint参数只适用于一对一, 或者一对多的关系. 至于多对多也是由双向的一对多关系组合而成, 是在一对多的关系上使用
    14. 是否在数据库中创建外键约束,默认为True

    其余字段参数

    1. models.DO_NOTHING
    2. 删除关联数据,引发错误IntegrityError
    3. models.PROTECT
    4. 删除关联数据,引发错误ProtectedError
    5. models.SET_NULL
    6. 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
    7. models.SET_DEFAULT
    8. 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
    9. models.SET
    10. 删除关联数据,
    11. a. 与之关联的值设置为指定值,设置:models.SET(值)
    12. b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
    13. # on_dalete实际应用
    14. on_delete参数:
    15. 1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
    16. 2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
    17. 3、断关联一定要通过逻辑保证表之间数据的安全,不要出现脏数据,代码控制
    18. 4、断关联
    19. 5、级联关系
    20. 作者没了,详情也没:on_delete=models.CASCADE
    21. 出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING
    22. 部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL
    23. 部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT

    3-5. 自关联字段参数

    需要在第一个参数中添加‘self’字符串,或写上它自己的表名(模型类名)

    parent = ForeignKey(to='self')

    3–6. related_name 和 related_query_name

    related_name

    1. # related_name 子查询反向操作时,使用的字段名,用于代替原反向查询时的'表名_set'。
    2. # 例如:
    3. class Classes(models.Model):
    4. name = models.CharField(max_length=32)
    5. class Student(models.Model):
    6. name = models.CharField(max_length=32)
    7. theclass = models.ForeignKey(to="Classes")
    8. # 当我们要查询某个班级关联的所有学生(反向查询)时,我们会这么写:
    9. models.Classes.objects.first().student_set.all()
    10. # 当我们在ForeignKey字段中添加了参数 related_name 后
    11. class Student(models.Model):
    12. name = models.CharField(max_length=32)
    13. theclass = models.ForeignKey(to="Classes", related_name="students")
    14. # 当我们要查询某个班级关联的所有学生(反向查询)时,我们会这么写:
    15. models.Classes.objects.first().students.all()

    related_query_name

    # related_query_name连表查询时, 反向查询操作时,使用的连接前缀,用于替换表

    4. 自定义字段

    1. class MyCharField(models.Field):
    2. # 1. 自定义独有参数
    3. def __init__(self, max_length, *args, **kwargs):
    4. self.max_length = max_length
    5. super().__init__(max_length=max_length, *args, **kwargs) # max_length一定要是关键字的形式传入
    6. # 2. 定义存储的类型及约束条件
    7. def db_type(self, connection):
    8. return 'Char(%s)' % self.max_length
    9. # 自定义字段使用
    10. class Text(models.Model):
    11. myfield = MyCharField(max_length=32, null=True)

    二. 准备表和基本数据

    1. 准备表

    1. from django.db import models
    2. # Create your models here.
    3. class User(models.Model):
    4. name = models.CharField(max_length=32, verbose_name='用户名')
    5. age = models.IntegerField(verbose_name='年龄')
    6. # register_time = models.DateField(verbose_name='年月日')
    7. register_time = models.DateTimeField(auto_now_add=True, verbose_name='年月日时分秒')
    8. """
    9. 提示: django自带的sqlite3数据库对日期格式不是很敏感 处理的时候容易出错
    10. DateField
    11. DateTimeField
    12. 两个重要参数
    13. auto_now: 每次操作数据的时候 该字段会自动将当前时间更新
    14. auto_now_add:在创建数据的时候会自动将当前创建时间记录下来 之后只要不认为的修改 那么就一直不变
    15. """
    16. def __str__(self):
    17. return self.name
    18. class Book(models.Model):
    19. title = models.CharField(max_length=32)
    20. price = models.DecimalField(max_digits=8, decimal_places=2)
    21. publish_time = models.DateTimeField(auto_now_add=True)
    22. authors = models.ManyToManyField(to='Author')
    23. publish = models.ForeignKey(to='Publish')
    24. def __str__(self):
    25. return self.title
    26. class Author(models.Model):
    27. name = models.CharField(max_length=32)
    28. age = models.IntegerField()
    29. author_detail = models.OneToOneField(to='AuthorDetail')
    30. def __str__(self):
    31. return self.name
    32. class Publish(models.Model):
    33. name = models.CharField(max_length=32)
    34. addr = models.CharField(max_length=64)
    35. email = models.EmailField() # varchar(254) 该字段类型不是给models看的 而是给的校验性组件看的
    36. def __str__(self):
    37. return self.name
    38. class AuthorDetail(models.Model):
    39. phone = models.BigIntegerField()
    40. addr = models.CharField(max_length=64)
    41. def __str__(self):
    42. return f'{self.phone}'

    2. 基本数据

    先往出版社表,作者表, 作者详情表准备一些数据。

    因为一对一关系外键和一对多差不多,我们用一对多来操作,把一对一的表先建立好,不做操作。

    出版社表是一个被图书表关联的表我们先建立这个被关联表。

    publish
    idemailaddr
    1东方出版社东方
    2北方出版社北方
    author
    idnameageauthor_detail_id
    1jason181
    2egon842
    3tank503
    author_detail
    idphoneaddr
    1110芜湖
    2120山东
    3130惠州

     

    三. 单表操作: 增删改

    1. 增

    1. # 1. 方式一: 自动增 .create
    2. models.User.objects.create(name='jason', age=73, register_time='2020-11-11 11:11:11')
    3. from datetime import datetime
    4. models.User.objects.create(name='jason', age=73, register_time=datetime.now().strftime('%Y-%m-%d %X'))
    5. import time
    6. models.User.objects.create(name='jason', age=73, register_time=time.strftime('%Y-%m-%d %X'))
    7. # 2. 方式二: 手动增 .save()
    8. user_obj = models.User(name='alex', age=84, register_time='2020-11-11 11:11:11')
    9. user_obj.save()

    2. 删

    1. # 1. 拿到QuerySet对象: 统一的删除
    2. res = models.User.objects.filter(pk=9).delete()
    3. print(res) # (1, {'app01.User': 1}) 第一个参数是被影响的行数
    4. models.User.objects.all().delete()
    5. """
    6. pk会自动查找到当前表的主键字段 指代的就是当前表的主键字段
    7. 用了pk之后 你就不需要指代当前表的主键字段到底叫什么了
    8. uid
    9. pid
    10. sid
    11. ...
    12. """
    13. # 2. 拿到用户对象: 单一针对性的删除
    14. user_obj = models.User.objects.filter(pk=11).first()
    15. user_obj.delete()

    3. 改

    1. # 1. 方式一: .update
    2. user_obj = models.User.objects.filter(pk=100).update(name='EGON_DSB')
    3. print(user_obj) # 0
    4. user_queryset = models.User.objects.filter(pk=100)
    5. print(user_queryset, bool(user_queryset)) # False
    6. # 2. 方式二: .get + 赋值 + .save()
    7. user_obj = models.User.objects.get(pk=100) # app01.models.DoesNotExist: User matching query does not exist.
    8. user_obj.name = 'EGON_DSB1'
    9. user_obj.save()
    10. """
    11. get方法返回的直接就是当前数据对象
    12. 但是该方法不推荐使用
    13. 一旦数据不存在该方法会直接报错
    14. 而filter则不会
    15. 所以我们还是用filter
    16. """

    四. 必知必会13条 (ORM提供的13条API)

    1. all() 查询所有

    1. '''
    2. 返回QuerySet对象. QuerySet对象内部包含所有数据对象
    3. '''
    4. user_queryset = models.User.objects.all()
    5. print(user_queryset) # , ,,...]>

    2. filter(**kwargs) 过滤

    1. '''
    2. 返回QuerySet对象. 内部包含与所给筛选条件相匹配的数据对象
    3. 不指定参数默认查询所有
    4. 带有过滤条件的查询, 当结果不存在返回空的QuerySet对象, 布尔值为False
    5. '''
    6. user_queryset = models.User.objects.filter(name='alex')
    7. print(user_queryset) # , ]>
    8. user_queryset = models.User.objects.filter()
    9. print(user_queryset) # , ,,...]>
    10. user_queryset = models.User.objects.filter(pk=9999)
    11. print(user_queryset, bool(user_queryset)) # False

    3. get(**kwargs)

    1. '''
    2. 直接获取数据对象
    3. 只能指定一个筛选条件. 如果指定的筛选条件返回的结果不唯一 或者 不存在 抛出异常
    4. '''
    5. user_queryset = models.User.objects.get(pk=1)
    6. print(user_queryset) # User object
    7. # models.User.objects.get(name='alex') # get() returned more than one User -- it returned 2!.
    8. # models.User.objects.get(pk=9999999) # User matching query does not exist.

    4. last()

    1. '''
    2. 获取QuerySet列表中最后一个数据对象.
    3. 用在QuerySet对象之后, 如果QuerySet对象为空, 再使用它返回None
    4. '''
    5. user_queryset = models.User.objects.filter(age=73)
    6. print(user_queryset) # , ]>
    7. user_obj = models.User.objects.filter(age=73).last()
    8. print(user_obj) # qwe
    9. user_obj = models.User.objects.filter(pk=99999).last()
    10. print(user_obj) # None

    5. first()

    1. '''
    2. 直接获取QuerySet列表中第一个数据对象.
    3. 用在QuerySet对象之后, 如果QuerySet对象为空, 再使用它返回None
    4. '''
    5. user_queryset = models.User.objects.filter(age=73)
    6. print(user_queryset) # , ,...]>
    7. user_obj = models.User.objects.filter(age=73).first()
    8. print(user_obj) # EGON_DSB1
    9. user_obj = models.User.objects.filter(pk=99999).first()
    10. print(user_obj) # None

    6. values(*field)

    1. '''
    2. 返回QuerySet对象. 内部是一种列表套字典的格式. 字典的key就是指定的字段名
    3. '''
    4. user_queryset = models.User.objects.values('name', 'age')
    5. print(user_queryset) #
    6. # 注意!!!: 指定字段不存在抛出异常.
    7. # django.core.exceptions.FieldError: Cannot resolve keyword 'xxxxxxxxxx' into field. Choices are: age, id, name, register_time
    8. user_queryset = models.User.objects.values('xxxxxxxxxx')
    9. print(user_queryset) #

    7. values_list(*field)

    1. '''
    2. 返回QuerySet对象.
    3. 内部是一种列表套元组的格式. 元组的第一个值就是指定的第一个字段对应的数据, 依此类推.
    4. '''
    5. user_queryset = models.User.objects.values_list('name', 'age')
    6. print(user_queryset) #
    7. # 注意!!!: 指定字段不存在抛出异常.
    8. # django.core.exceptions.FieldError: Cannot resolve keyword 'xxxxxxxxxx' into field. Choices are: age, id, name, register_time
    9. user_queryset = models.User.objects.values_list('xxxxxxxxxx')
    10. print(user_queryset) #

    8. distinct() 去重

    1. '''
    2. 注意!!!: 必须排除主键字段 或 唯一字段才会有意义
    3. 要排除使用filter无法筛选. 一般用在.values() 或 .value_list()后面
    4. '''
    5. user_queryset = models.User.objects.values('age')
    6. print(user_queryset) #
    7. dis_user_queryset = user_queryset.distinct()
    8. print(dis_user_queryset) #

    9. order_by(*field) 排序

    1. '''
    2. 对查询结果排序. 默认升序. 如果想要降序在对应要查询的字段前指定`-`号
    3. '''
    4. user_queryset = models.User.objects.values('age')
    5. print(user_queryset) #
    6. user_queryset_asc = user_queryset.order_by('age')
    7. print(user_queryset_asc) #
    8. user_queryset_desc = user_queryset.order_by('-age')
    9. print(user_queryset_desc) #

    10. reverse()

    1. '''
    2. 注意!!!: 反转的前提是数据已经排过序. 没排过序reverse将不起作用.
    3. '''
    4. user_queryset_desc = models.User.objects.values('age').reverse()
    5. print(user_queryset_desc) #
    6. user_queryset_desc = models.User.objects.values('age').order_by('-age')
    7. print(user_queryset_desc) #
    8. user_queryset_desc_rev = user_queryset_desc.reverse()
    9. print(user_queryset_desc_rev) #

    11. count()

    1. '''
    2. 查询QuerySet内部所包含的数据对象的个数
    3. '''
    4. user_queryset = models.User.objects.all()
    5. print(user_queryset) # , ]>
    6. all_user_queryset = models.User.objects.count()
    7. print(all_user_queryset) # 2
    8. user_queryset = models.User.objects.filter(name='EGON_DSB1')
    9. print(user_queryset) # ]>
    10. all_user_queryset = models.User.objects.filter(name='EGON_DSB1').count()
    11. print(all_user_queryset) # 1

    12. exclude(**kwargs):

    1. '''
    2. 排除. 查询与所给筛选条件不匹配的
    3. '''
    4. user_queryset = models.User.objects.exclude(age=73)
    5. print(user_queryset) # , ]>
    6. print(user_queryset.values('age')) #
    7. # 注意!!!: 排除不存在的返回空的QuerySet对象
    8. user_queryset = models.User.objects.exclude(age=11111111111111)
    9. print(user_queryset) #

    13. exists()

    1. '''
    2. 查找所返回的QuerySet结果包含数据,就返回True,否则返回False
    3. '''
    4. user_queryset = models.User.objects.filter(pk=999999).exists()
    5. print(user_queryset) # False
    6. user_queryset = models.User.objects.all().exists()
    7. print(user_queryset) # True

    五. 查看内部封装的sql语句的2种形式

    1. # 第一种: QuerySet.query
    2. user_queryset = models.User.objects.values_list('name', 'age')
    3. print(user_queryset.query) # SELECT `app01_user`.`name`, `app01_user`.`age` FROM `app01_user`
    4. # 第二种: 执行脚本时打印日志显示到终端. 复制以下日志内容到settings.py中
    5. LOGGING = {
    6. 'version': 1,
    7. 'disable_existing_loggers': False,
    8. 'handlers': {
    9. 'console':{
    10. 'level':'DEBUG',
    11. 'class':'logging.StreamHandler',
    12. },
    13. },
    14. 'loggers': {
    15. 'django.db.backends': {
    16. 'handlers': ['console'],
    17. 'propagate': True,
    18. 'level':'DEBUG',
    19. },
    20. }
    21. }

    六. 神奇的双下划线查询

    1. 参数介绍

    1. '''
    2. field__gt=value field__lt=value
    3. field__gte=value field__lte=value
    4. field__in=[value1, value2, ...]
    5. field__range=[value1, value2]
    6. field__contains='substring' field__icontains='substring'
    7. field__startswith='substring' field__endswith='substring'
    8. field__istartswith='substring' field__iendswith='substring'
    9. field__year='2020' field__month='1' field__day='30'
    10. field__year=2020 field__month=1' field__day=30
    11. '''

    2. 实例操作

    1. # 查询年龄大于35岁的数据
    2. models.User.objects.filter(age__gt=35)
    3. # 查询年龄小于35岁的数据
    4. models.User.objects.filter(age__lt=35)
    5. # 查询年龄大于等于33岁 查询年龄小于等于30岁
    6. models.User.objects.filter(age__gte=30)
    7. models.User.objects.filter(age__lte=30)
    8. # 查询年龄是22 或者 30 或者 73
    9. models.User.objects.filter(age__in=[22, 30, 73])
    10. # 查询年龄在18到40岁之间的 首尾都要
    11. models.User.objects.filter(age__range=[18, 40])
    12. # 模糊查询: 查询出名字里面含有`s`的数据(区分大小写) 查询出名字里面含有`s`的数据(忽略大小写)
    13. models.User.objects.filter(name__contains='s')
    14. models.User.objects.filter(name__icontains='s')
    15. # 以`j`开头(区分大小写) 以`j`开头(不区分大小写) 以`5`结尾(区分大小写)
    16. models.User.objects.filter(name__startswith='j')
    17. models.User.objects.filter(name__istartswith='j')
    18. models.User.objects.filter(name__endswith='5')
    19. # 查询出注册时间是 2020 1月的
    20. models.User.objects.filter(register_time__year=2020)

    3. 总结

    1. # 注意: 争对字段使用. 如: field__gt
    2. __gt __lt __gte __glt
    3. __in=[] __range=[start, stop]
    4. __contains __icontains i全称忽略ignore
    5. __startswith __istartswith
    6. __endswith __iendswith
    7. __year='2020' __year=2020
    8. __month='1' __month=1
    9. __day='20' __day=20

  • 相关阅读:
    推送多架构镜像到同一仓库
    考研C语言复习进阶(6)
    【ArcGIS风暴】ArcGIS标注和注记的区别及用法案例详解
    网络编程 lesson5 IO多路复用
    Eclipse创建Maven Project跟Maven Module
    OS 进程同步
    软考 系统架构设计师系列知识点之软件可靠性基础知识(6)
    maven的下载、配置
    【计算摄影】相机成像原理:从光到JPEG图像
    Day39——互斥锁,线程技术
  • 原文地址:https://blog.csdn.net/m0_71115526/article/details/134420003