Django--(2)模型(Model)属性与参数整理

模型

模型类属性命名限制:

  1. 不能是python的保留关键字
  2. 不能使用连续的下划线. 这是由django的查询方式决定的
  3. 定义属性时需要指定字段类型. 通过字段类型的参数指定选项. 语法如下:属性名=models.字段类型(选项)

文件app/models.py 模板格式

from django.db import models
class ModelName(models.Model):  # 模型类
	Field1 = models.XXXField(...)
	Field2 = models.XXXField(...)
	...
	class Meta:  #元选项
		db_table = ...
		other_metas = ...

模型类

每个模型类都可以被映射为数据库中的一个数据表,类类属性被映射为数据字段,除此之外,数据库表的主键、外键、约束等也通过类属性完成定义

模型类属性

属性描述
AutoField一个自动递增的整型字段,添加记录时会自动增长
AutoField 字段通常会用于充当数据表的主键
若模型没有指定主键字段,则Django 自动添加一个 AutoField字段
IntegerField用于保存一个整数
SmallIntegerField类似于 IntegerField
但只具有较小的输入范围,具体范围依赖于所使用的数据库
BigIntegerField64位整型字段
BinaryField二进制数据字段
只能通过 types 对其赋值
FloatField浮点型字段
定义本字段时必须传入 max_digitsdecimal_places 参数
用于定义总位数(不包括小数点和符号)和小数位数
DecimalField十进制浮点数
max_digits参数表示总位
decimal_places 参数表示小数位数
CommaSeparatedIntegerField用于存放逗号分隔的整数值
相较与普通的 CharField, 它有特殊的表单数据验证要求
DurationField存储时间周期,
用 Python 的 timedelta 类型构建
EmailField一个带检查 Email 合法性的CharField
FileField一个文件上传字段
在定义本字段时传入参数 upload_to,用于保存上载文件的服务器文件系统路径
这个路径必须 包含 striftime formatting, 该格式将上载 文件的 date/time 替换
FilePathField按目录限制规则选择文件
定义本字段必须传入参数 path ,用于限制目录
ImageField类似于 FileField,同时验证上传对象是否是一个合法的图片
有两个可选参数 height_fieldwidth_field
如果提供这两个参数,则图片将按照提供的高度和宽度规格保存
该字段要求安装 Python Imaging 库
IPAddressField一个字符串形式的IP地址
例如: 192.23.250.2
NullBooleanField类似于 BooleanField, 但比其多一个None选项
PhoneNumberField带有美国风格的电话号码校验的 CharField
格式为 XXX-XXX-XXXX
SlugField只包含字母、数字、下划线和连字符的输入字段
通常用于URL
URL用于保存URL
USStateField美国州名的缩写字段,由两个字母组成
XMLFieldXML字段
是具有XML合法验证的TextField
属性描述相对应的HTML标签
BooleanField布尔字段<input type = "checkbox">
CharField字符串字段,用于较短的字符串单行输入
<input type = "text">
TextField大容量文本字段多行编辑框 <textarea>
DateField日期字段<input type="text">、一个JavaScript 日期和一个“today” 快捷按键
有两个额外可选参数:
auto_now 当对象被保存时,将该字段的值设置为当前时间
auto_now_add 当对象被首次创建时,将该字段的值设置为当前时间
DateTimeField类似于 DateField,但同时支持于时间的输入
TimeField时间字段,类似于 DateTimeField
但只能表达和输入时间

模型类属性参数

参数描述
max_length定义字符的长度
例如 : headline = models.CharField(max_length=255)
primary_key设置一个模型的主键字段
例如:primary_key=true
null定义是否允许相对应的数据库字段为Null,
默认设置为 False
是一个数据库中的非空约束
blank定义字段是否可以为空
blank 用于字段的HTML表单验证,即判断用户是否可以不输入数据
choices定义字段的可选值
本字段的值应该是一个包含二维元素的元组
元组的每个元素的第一个值是实际存储的值,
第二个值是HTML页面进行选择时显示的值
default设置默认值
例如: default="please input here"
help_textHTML页面中输入控件的帮助字符串
unique是否为字段定义数据库的唯一约束
无名参数可以设置该字段在HTML页面中的人性化名称 例如:
level = models.CharField("请为本条信息评级",max_length=1,choices=LEVELS)
如果不设置本参数,则字段本身将被显示在 HTML 页面中作为输入提示
db_index若值为True,则在表中会为此字段创建索引
默认False
db_column字段的名称
如果未指定,则使用属性的名称

元选项 (Meta类)

通过此类可以定义模型元数据,比如:数据库表名,数据默认排序方式等

属性描述
abstract:标识本类是否为抽象基类
True or False
app_label:定义本类所属的应用
db_table:映射的数据库表名,例如: db_table=‘moments’
如果在Meta中不提供 db_table 字段,则Django 会为模型自动生成数据表名,生成的格式为“应用名_模型名”,例如:应用app的模型 Comment 的默认数据表名为 app_comment
db_tablespace:映射的表空间名称
表空间的概念只在某些数据库如 Oracle 中存在,不存在表空间的概念的数据库将忽略此字段
default_related_name:定义本模型的反向关系引用名称,默认与模型名一致
get_latest_by:定义按哪个字段值排列以获得模型的开始或结束记录
本属性值通常指向一个日期或整型的模型字段
managed:True or False
定义 Django的 manage.py 命令行工具是否管理本模型。
默认为 True,若将其设置为 False,则运行 python manage.py migrate 时将不会在数据库中生成本模型的数据表,所以需要手工维护数据库的定义
order_with_respect_to:定义本模型可以按照某外键引用的关系排序
order:本模型记录的默认排序字段,可以设置多个字段,默认以升序排列,
若以降序排列则表示要在字段名前加负号("-")
例如:定义 user_name 字段升序 和 pub_date 降序排列
order = ['user_name','-pub_date']
dafault_permissions:模型操作权限
默认为 default_permisstions=('add','change','delete')
proxy"=:True or False
本模型及所有继承自本模型的子模型是否为代理模型
required_db_features:定义底层数据库所必须具备的特性
例如:required_db_features=['gis_enabled']只将本数据模型生成在满足 gis_enabled 特性的数据库中
required_db_vendor:定义底层数据库类型
比如 SQLite,PostgreSQL,MySQL,Oracle
如果定义了本属性,则模型只能在其声明的数据库中被维护
unique_together:用来设置的不重复的字段组合,必须唯一(可以将多个字段做联合唯一)
例如:unique_together = (("user_name","pub_date"),)
定义了每个 user_name 在同一个 pub_date 中只能有一条数据表记录
因为 unique_together 本身是一个元组,所以可以设置多个这样的唯一约束
index_together:定义联合索引的字段,可以设置多个
例如:index_together = [["pub_date","deadline"],]
verbose_name:指明一个易于理解和表述的单数形式的对象名称。如果这个值没有被设置,则Django将会使用该model的类型的分词形式作为它的对象表述名,即 CamelCase 将会被转换为camel case
verbose_name_plural:指明一个易于理解和表述的复数形式的对象名称

修改默认生成的表名,

#-*- coding:utf-8 -*-
from django.db import models

# Create your models here.
#------------- 一对多 ----------------------
#图书类
class BookInfo(models.Model):
    '''图书模型类'''
    #id 自动生成
    #图书名称
    btitle = models.CharField(max_length=20)
    #出版日期
    bpub_date = models.DateField()
    #阅读量
    bread = models.IntegerField(default=0)
    #评论量
    bcomment = models.IntegerField(default=0)
    #删除标记
    isDelete = models.BooleanField(default=False)

    def __str__(self):
        # 返回书名
        return self.btitle

    class Meta:
        db_table = 'bookinfo' #指定模型类对应的表明

通过模型操作数据库

查询

模型类.objects.属性

函数名功能返回值说明
get返回表中满足条件的一条且只能有一条数据返回值是一个模型类对象参数中写查询条件
1. 如果查到多条数据,则抛异常MultipleObjectsReturned
2. 查询不到数据,则抛异常:DoesNotExist
all返回模型类对应表格中的所有数据返回值是QuerySet类型查询集
filter返回满足条件的数据返回值是QuerySet类型参数写查询条件
exclude返回不满足条件的数据返回值是QuerySet类型参数写查询条件
order_by对查询结果进行排序返回值是QuerySet类型参数中写根据哪些字段进行排序
降序:字段前加 ‘-’号

练习与演示
准备练习数据集:使用博客 Django_182_入门指南 图书数据表进行练习
在这里插入图片描述
查询集
all, filter, exclude, order_by调用这些函数会产生一个查询集,QuerySet类对象可以继续调用上面的所有函数
查询集特性

  1. 惰性查询:
    只有在实际使用查询集中的数据的时候才会发生对数据库的真正查询
  2. 缓存:
    当使用的是同一个查询集时,第一次使用的时候会发生实际数据库的查询,然后把结果缓存起来,之后再使用这个查询集时,使用的是缓存中的结果

限制查询集
3. 可以对一个查询集进行取下标或者切片操作来限制查询集的结果, 下标不允许为负数
4. 对一个查询集进行切片操作会产生一个新的查询集

取出查询集的数据

方法说明
b[0]如果b[0]不存在,抛异常:IndexError
b[0:1].get()如果b[0:1].get()不存在,抛异常:DoesNotExist

exists() 函数判断一个查询集是否有数据,返回 True,False

在这里插入图片描述

get

查询有id=5的数据

book = BookInfo.objects.get(id=5)

等效

book = BookInfo.objects.get(id__exact=5)

在这里插入图片描述
在这里插入图片描述
使用查询的id号没有数据,抛的异常
在这里插入图片描述
使用get查询出多个数据,抛出异常
在这里插入图片描述

all

在这里插入图片描述

filter,get,exclude 参数的使用格式

参数格式 模型属性名__条件名=值

判等条件  条件名:exact

查询 id=5 的数据

book = BookInfo.objects.get(id__exact=5)

查询 isDelete=0 的数据

 books = BookInfo.objects.filter(isDelete__exact=0)

在这里插入图片描述

模糊查询

条件名 contains 包含
查询书名包含 “传” 的图书

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

在这里插入图片描述
条件名 endswith 以…结尾
查询以 “部” 结尾的图书

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

在这里插入图片描述
条件名 startswith 以…开头
查询 以“流” 开头的图书

books = BookInfo.objects.filter(btitle__startswith='流')

在这里插入图片描述

空查询 isnull

查询图书名 不为空 的图书

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

在这里插入图片描述
查询图书名 为空 的图书

books = BookInfo.objects.filter(btitle__isnull=True)

范围查询 in

查询 id 为 5,7,17 中图书

books = BookInfo.objects.filter(id__in = [5,7,17])

在这里插入图片描述

比较查询

gt (great than) 大于
lt (less than) 小于
gte (great than equal) 大于等于
lte (less than equal) 小于等于
查询 id>0 的图书

books = BookInfo.objects.filter(id__gt = 10)

在这里插入图片描述

日期查询

条件名 year
查询 1980 年发表的图书

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

在这里插入图片描述
条件名 month
查询 11月 发表的图书

books = BookInfo.objects.filter(bpub_date__month=11)

在这里插入图片描述
查询 1980-1-1 之后 发表的图书

from datetime import date
books = BookInfo.objects.filter(bpub_date__gt=date(1980,1,1))

在这里插入图片描述

exclude 不等于

查询 id 不等于 5 的数据

 books = BookInfo.objects.exclude(id=5)

在这里插入图片描述

order_by 排序

查询所有图书的信息,按照 id 从小到大进行排序

books = BookInfo.objects.all().order_by('id')

在这里插入图片描述

查询所有图书的信息,按照 id 从大到小进行排序

books = BookInfo.objects.all().order_by('-id')

在这里插入图片描述
把 id>3 的图书信息按照阅读量从大到小排序显示

books = BookInfo.objects.filter(id__gt=3).order_by('-bread')

在这里插入图片描述

F对象:类属性之间的比较

查询图书阅读量>评论量的图书

from django.db.models import F
books = BookInfo.objects.filter(bread__gt=F('bcomment'))

在这里插入图片描述
查询图书阅读量> 2倍评论量的图书

from django.db.models import F
books = BookInfo.objects.filter(bread__gt=F('bcomment')*2)

在这里插入图片描述

Q对象:查询条件之间的逻辑比较

&
查询 id>3 并且阅读量 大于30 的图书信息

books = BookInfo.objects.filter(id__gt=3,bread__gt=30)

等效

from django.db.models import Q
books = BookInfo.objects.filter(Q(id__gt=3)&Q(bread__gt=30))

在这里插入图片描述
在这里插入图片描述
|
查询 id>3 或者 阅读量>30 的图书

from django.db.models import Q
books = BookInfo.objects.filter(Q(id__gt=3)|Q(bread__gt=30))

在这里插入图片描述
~
查询 id 不等于5 的图书

from django.db.models import Q
books = BookInfo.objects.filter(~Q(id=5))

在这里插入图片描述

聚合: 对查询结果进行聚合操作

使用aggregate()函数来使用聚合,返回是 字典

sum 求和

查询所有图书阅读量的总和

from django.db.models import Sum
bread_num = BookInfo.objects.all().aggregate(Sum('bread'))

在这里插入图片描述

count 统计

查询所有图书的数目

from django.db.models import Count
books_num = BookInfo.objects.all().aggregate(Count('id'))

在这里插入图片描述
等效

from django.db.models import Count
books_num = BookInfo.objects.aggregate(Count('id'))

在这里插入图片描述
count() 函数:统计满足条件的数目,返回的是一个数字
统计所有图书的数目

books_num = BookInfo.objects.all().count()

在这里插入图片描述
统计 id>3 的所有图书的数目

books_num = BookInfo.objects.filter(id__gt=3).count()

在这里插入图片描述

avg 求平均值
max 求最大值
min 求最小值

插入、更新、删除

调用一个模型类对象save()方法的时候就可以实现对模型类对应数据表的插入和更新
调用一个模型类对象delete()方法的时候就可以实现对模型类对应数据表的删除

模型类关系

一对多关系

例如:一本图书 有 多个英雄
models.ForeignKey()定义在多的类中
CTTIC/app/models.py

from django.db import models

# Create your models here.
#图书类
class BookInfo(models.Model):
    '''图书模型类'''
    #id 自动生成
    #图书名称
    btitle = models.CharField(max_length=20)
    #出版日期
    bpub_date = models.DateField()
    #阅读量
    bread = models.IntegerField(default=0)
    #评论量
    bcomment = models.IntegerField(default=0)
    #删除标记
    isDelete = models.BooleanField(default=False)

    def __str__(self):
        # 返回书名
        return self.btitle

#英雄人物类
class HeroInfo(models.Model):
    #英雄名 hname
    hname = models.CharField(max_length=20)
    # 性别 hgender,并指定默认值
    hgender = models.BooleanField(default=False)
    # 备注 hcomment
    hcomment = models.CharField(max_length=128)
    isDelete = models.BooleanField(default=False)
    #关系属性,建立图书类和英雄人物类之间的一对多关系
    hbook = models.ForeignKey('BookInfo')

    def __str__(self):
        return self.hname
关联查询(一对多)

使用博客 Django_182_入门指南 图书数据表进行练习
在这里插入图片描述
查询图书信息,要求图书关联的英雄的描述包含‘八’

books = BookInfo.objects.filter(heroinfo__hcomment__contains='八')

在这里插入图片描述
查询图书信息,要求图书中的英雄的 id>3

books = BookInfo.objects.filter(heroinfo__id__gt=3)

在这里插入图片描述
查询书名为 “天龙八部” 的所有英雄

from app.models import HeroInfo
heros = HeroInfo.objects.filter(hbook__btitle='天龙八部')

在这里插入图片描述
总结
通过多类的条件查询一类的数据
一类名.objects.filter(多类名小写__多类属性名__条件名)
通过一类的条件查询多类的数据
多类名.objects.filter(关联属性__一类属性名__条件名)

多对多关系

例如:一个老师有多个学生,一个学生有多个老师
models.ManyToManyField() 定义在哪个类中都可以

#-*- coding:utf-8 -*-
from django.db import models
#老师信息
class TeacherInfo(models.Model):
    #老师姓名
    tname = models.CharField(max_length=20)
    # 老师描述
    tcomment = models.TextField()

# 学生信息
class StudentInfo(models.Model):
    # 学生姓名
    sname = models.CharField(max_length=20)
    # 学生描述
    scomment = models.TextField()
    teacher = models.ManyToManyField('TeacherInfo')

在这里插入图片描述
在这里插入图片描述

一对一关系

例如:员工基本信息 对应 员工详细信息
models.OneToOneField() 定义在哪个类中都可以

#-*- coding:utf-8 -*-
from django.db import models
#员工基本信息类
class EmployeeBasicInfo(models.Model):
    #姓名
    name = models.CharField(max_length=20)
    #年龄
    age = models.IntegerField()
    # 性别,默认False对应男
    gender = models.BooleanField(default=False)

    def __str__(self):
        return self.name

#员工详细信息类
class EmployeeDetailInfo(models.Model):
    #联系地址
    addr = models.CharField(max_length=255)
    #教育经历
    education = models.TextField()
    #关系属性,代表一对一关系
    employee_basic = models.OneToOneField('EmployeeBasicInfo')

    def __str__(self):
        return self.addr

自关联

自关联是一种特殊的一对多的关系,使用models.ForeignKey()关联
在这里插入图片描述
aParent_id 表示该地区上级所属的id号,若该地区为父级,则为NULL(为空)

#-*- coding:utf-8 -*-
from django.db import models
class AreaInfo(models.Model):
    '''地区模型类'''
    # 地区名称
    atitle = models.CharField(max_length=20)
    # 关系属性:代表当前地区的父级地区对应id,允许为空
    aParent = models.ForeignKey('self',null=True,blank=True)

执行迁移文件生成表

python manage.py makemigrations
python manage.py migrate

在这里插入图片描述
插入测试数据

INSERT INTO app_areainfo VALUES ('110000', '北京市', NULL);
INSERT INTO app_areainfo VALUES ('110100', '北京市', '110000');
INSERT INTO app_areainfo VALUES ('110101', '东城区', '110100');
INSERT INTO app_areainfo VALUES ('110102', '西城区', '110100');
INSERT INTO app_areainfo VALUES ('110103', '朝阳区', '110100');
INSERT INTO app_areainfo VALUES ('110104', '丰台区', '110100');
INSERT INTO app_areainfo VALUES ('110105', '石景山区', '110100');
INSERT INTO app_areainfo VALUES ('110106', '海淀区', '110100');
INSERT INTO app_areainfo VALUES ('110107', '门头沟区', '110100');

此处数据链接
链接:https://pan.baidu.com/s/1EPQ-ztSaB7n5KFGTk98phw
提取码:drye
复制这段内容后打开百度网盘手机App,操作更方便哦
在这里插入图片描述
显示 广东 的上级地区 及 下级地区
CTTIC/app/views.py 中添加视图函数

#-*- coding:utf-8 -*-
from django.shortcuts import render
from app.models import AreaInfo
def areas(request):
    '''获取广州市的上级及下级地区'''
    # 获取广州市的信息
    area = AreaInfo.objects.get(atitle='广州市')
    # 查询广州市的上级地区
    parent = area.aParent
    # 查询广州市的下级地区
    children = area.areainfo_set.all()
    context = {
        'area':area,
        'parent':parent,
        'children':children,
    }
    return render(request,'app/areas.html',context)

新建 CTTIC/templates/app/areas.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自关联案例</title>
</head>
<body>
<h1>当前地区</h1>
{{ area.atitle }}   <br/>
<h1>父级地区</h1>
{{ parent.atitle }} <br/>
<h1>下级地区</h1>
<ul>
    {% for child in children %}
        <li>{{ child.atitle }}</li>
    {% endfor %}
</ul>
</body>
</html>

CTTIC/app/urls.py 配置路由

#-*- coding:utf-8 -*-
from django.conf.urls import url
from app import views
urlpatterns = [
    # 通过url函数设置url配置项
    url(r'^areas$',views.areas),
]

在这里插入图片描述

面向对象 ORM

Django模型层 ORM 的一个强大之处是对模型继承的支持,该技术将Python面向对象的编程方法与数据库面向关系表的数据结构有机结合
Django支持三种风格的模型继承

  1. 抽象类继承:
    通过 Meta 中定义属性 abstract = True
    父类继承 models.Model,但不会在底层数据库中生成相应的数据表
    父类的属性列存储在子类的数据表中
    将某些字段定义在抽象基类中,免于重复定义这些字段
  2. 多表继承:
    多表继承的每个模型类都在底层数据库中生成相应的数据表管理数据
    在多表继承技术中,无论是父表还是子表都会用数据库中相应的数据表维护模型数据,父类中的字段不会重复第在多个子类的相关数据表中进行定义
    从某种意义上讲,多表继承才是真正面向对象的ORM技术
    多表继承不需要特殊的关键字
    在Django内部通过在父类模型和子模型之间建立一对一关系来实现多表继承技术
  3. 代理模型继承:
    通过在子类 Meta 中定义 proxy=True 来实现
    父类用于在底层数据库中管理数据表
    而子类不定义数据列,只定义查询数据集的排序方式等元数据
    子类只用于管理父类的数据,而不实际存储数据
    使用原因:
    是子类中新的特性不会影响父类模型及其已有代码的行为

抽象类继承

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
#父类
class MessageBase(models.Model):
    content = models.CharField(max_length=100,null=True)
    user_name = models.CharField(max_length=80,null=True)
    pub_date = models.DateField(null=True)
    
    class Meta:
        abstract = True #定义本类为抽象基类      
# 子类
class Moment(MessageBase):
    headline = models.CharField(max_length=50)  
LEVELS = (
    ('1','Very good'),
    ('2','Good'),
    ('3','Normal'),
    ('4','Bad'),
)
# 子类
class Comment(MessageBase):
    level = models.CharField(max_length=1,choices = LEVELS)

3个类映射到数据库后,会被定义为两个数据表

数据表 moment: 有 id,content,user_name,pub_date,headline 等5个字段
数据表 comment: 有 id,content,user_name,pub_date,level 等5个字段
在这里插入图片描述

多表继承

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class MessageBase(models.Model):
    content = models.CharField(max_length=100,null=True)
    user_name = models.CharField(max_length=80,null=True)
    pub_date = models.DateField(null=True)
class Moment(MessageBase):
	headline = models.CharField(max_length=50)
class Comment(MessageBase):
	level = models.CharField(max_length=1,choices=LEVELS)

生成3个数据表
数据表 MessageBase: 有 id,content,user_name,pub_date 等4个字段
数据表 Moment: 有id,headline等两个字段
数据表 Comment: 有 id,level 等两个字段

代理类继承

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class Moment(models.Model):
    content = models.CharField(max_length=100,null=True)
    user_name = models.CharField(max_length=80,null=True)
    pub_date = models.DateField(null=True)
    headline = models.CharField(max_length=50)
class OrderedMoment(Moment):
	class Meta:
		proxy = True;
		ordering = ["-pub_date"]
  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值