Django模型层基本概念
所有Django模型继承<django.db.models.Model>类
通过类属性定义模型字段,如:models.XXField
通过模型类中的Meta子类定义模型元数据(非字段的其他数据),如:数据库表名,数据默认排序方式
常见Meta类属性:
- abstract:True or False,标志本类是不是抽象基类
- app_label:定义本类所属的应用,如 app_label='myapp'
- db_table:映射的数据表名,如:db_table='moment'
- db_tablespace:映射的表空间名称,只存在某些数据库如Oracle中
- default_related_name:定义本模型的反向关系引用名称
- get_latest_by:定义按哪个字段值排列以获得模型的开始或结束记录
- managed:True or False,定义Django的manage.py命令行工具是否管理本模型
- order_with_respect_to:定义本模型可以按照某外键引用的关系排序
- ordering:默认为升序,字段前加上'-'为降序
- default_permissions:模型操作权限,默认为 =('add', 'change', 'delete')
- proxy:True or False,本模型及所有继承自本模型的子模型是否为代理模型
- required_db_features:定义底层数据库所必须具备的特性
- required_db_vendor:定义底层数据库的类型,如 MySQL、Oracle
- unique_together:用来设置的不重复的字段组合,必须唯一
- index_together:定义联合索引的字段,可以设置多个
- verbose_name:指明一个易于理解和表述的单数形式的对象名称,如果该值没有设置,对象的表述名为对象名的小写分词形式,如 CamelCase——> camel case
- verbose_name_plural:指明一个易于理解和表述的复数形式的对象名称
普通字段是指模型类中除外键关系外的数据字段属性,提供以下信息:
- 在数据库中用什么类型定义模型字段
- 用什么样的HTML标签显示模型字段
- 需要什么样的HTML表单数据验证
常用普通字段:
- AutoField:通常只用于充当数据表的主键,没有定义此项时,会自动生成
- BigIntegerField:64位整型字段
- BinaryField:二进制数据字段
- BooleanField:布尔字段
- CharField:字符串字段
- TextField:大容量文本字段
- CommaSeparatedIntegerField:用于存放逗号分隔的整数值
- DateField:日期字段
- DateTimeField:类似于DateField,但同时支持时间的输入
- DurationField:存储时间周期
- EmailField:一个检查Email合法性的CharField
- FileField:一个文件上传字段,必须传入参数upload_to,即上传路径
- FilePathField:按目录限制规则选择文件,必须传入参数path
- FloatField:浮点型字段
- ImageField:一个图片上传字段,同时会验证图片合法性,可选参数height_field、width_field,要求安装Python Imaging库
- IntegerField:用于保存整数
- IPField:一个字符串形式的IP地址
- NullBooleanField:类似BooleanField,但多了None选项
- PhoneNumberField:带美国风格的电话校验的CharField
- PositiveIntegerField:只能输入非负数的IntegerField
- SlugField:只包含字母、数字、下划线和连字符的输入字段,通常用于URL
- SmallIntegerField:类似于IntegerField,适合较小的整数
- TimeField:时间字段,类似DateTimeField,但只能表达和输入时间
- URLField:用于保存URL
- USStateField:美国州名的缩写字段
- XMLField:XML字符字段,是具有XML合法性验证的TextField
常用字段参数:
- null:定义是否允许相对应的数据库字段为null,默认值为False,数据库中的非空约束
- blank:定义字段是否可以为空,HTML表达验证
- choices:定义字段的可选值
- default:设定默认值
- help_text:HTML页面中输入空间的帮助字符串
- primary_key:定义字段是否为主键
- unique:是否为字段定义数据库的唯一约束
基本查询:
Django通过模型的objects对象实现模型数据查询
过滤器:
- filter(**kwargs):返回符合筛选结果的数据集:
X.objects.filter(pub_date__year=2015)
- exclude(**kwargs):返回不符合筛选结果的数据集:
X.objects.filter(pub_date__year=2015).exclude(pub_date__month=1)
PS:两者可以结合使用
Django独特的字段查询(filed lookup):字段名称__谓词(双下滑线)
字段查询谓词:X.objects.filter.
- exact:精确等于 (id__exact=1)
- iexact:大小写不敏感等于 (headline__iexact='I like this')
- contains:模糊匹配 (headline__contains='good')
- in: 包含 (id__in[1, 5, 9])
- gt: 大于 (n_visit__gt=30)
- gte: 大于等于
- lt: 小于
- lte: 小于等于
- startswith: 以...开头 (body_text__startswith='Hello')
- endswith: 以...结尾
- range: 在...范围内 (pub_date__range=(start_date, end_date))
- year: 年
- month: 月
- day: 日
- week_day:星期几
- isnull:是否为空
还提供 - get()查询单条记录:x.objects.get(id_exact=1)
- 类似于切片的操作:x.objects.all()[:10]
- order_by操作:x.objects.order_by('name')
数据保存与删除:
定义了统一的save(),用于完成模型的 Insert 和 Update 操作
定义了delete()用于删除记录
关系操作:
利用数据表之间的关系进行数据建模和业务开发是关系数据库最主要的功能
1、一对一关系(OneToOneField)
from django.db import models
class Account(models.Model):
user_name = models.CharField(max_lenght=80)
password = models.CharField(max_length=255)
reg_date = models.DateField()
# __unicode__()函数用于定义模型的显示字符串
def __unicode__(self):
return 'Account: %s' % self.user_name
class Contact(models.Model):
# on_delete参数定义当被关联模型的记录被删除时本模型的记录如何处理
# models.CASCADE用于定义本记录也被删除
account = models.OneToOneField(Account, on_delete=models.CASCADE, primary_key=True)
zip_code = models.CharField(max_length=10)
address = models.CharField(max_length=80)
mobile = model.CharField(max_length=20)
def __unicode__(self):
return '%s %s' % (self.account.user_name, mobile)
2、一对多关系
from django.db import models
class Account(models.Model):
user_name = models.CharField(max_lenght=80)
password = models.CharField(max_length=255)
reg_date = models.DateField()
def __unicode__(self):
return 'Account: %s' % self.user_name
class Contact(models.Model):
account = models.ForeignKey(Account, on_delete=models.CASCADE, primary_key=True)
zip_code = models.CharField(max_length=10)
address = models.CharField(max_length=80)
mobile = model.CharField(max_length=20)
def __unicode__(self):
return '%s %s' % (self.account.user_name, mobile)
3、多对多关系
from django.db import models
class Account(models.Model):
user_name = models.CharField(max_lenght=80)
password = models.CharField(max_length=255)
reg_date = models.DateField()
def __unicode__(self):
return 'Account: %s' % self.user_name
class Contact(models.Model):
account = models.ManyToManyField(Account)
zip_code = models.CharField(max_length=10)
address = models.CharField(max_length=80)
mobile = model.CharField(max_length=20)
def __unicode__(self):
return '%s %s' % (self.account.user_name, mobile)
面向对象ORM:
Django支持三种风格的模型继承
1、抽象类继承:父类继承自models.Model,但不会在底层数据库生成相应的数据表
from django.db import models
class MessageBase(models.Model):
id = models.AutoField()
content = models.CharField(max_length=100)
user_name = models.CharField(max_length=80)
pub_date = models.DateField()
class Meta:
abstract = True
class Moment(MessageBase):
headline = models.CharField(max_length=50)
LEVELS = (
('1', 'Very good')
('2', 'Good')
('3', 'Normal')
('4', 'Bad')
)
class Coment(MessageBase):
level = models.CharField(max_length=1, choices=LEVELS)
迁移数据后,会定义两个数据表:
数据表 Moment:有id、content、user_name、pub_date、headline
数据表 Comment:有id、content、user_name、pub_date、level
2、多表继承:每个模型都在数据库中生成相应的数据表管理数据,父类中的字段不会重复地在多个子类的相关数据表中定义,从这个意义讲,多表继承才是真正的面向对象的ORM技术
from django.db import models
class MessageBase(models.Model):
id = models.AutoField()
content = models.CharField(max_length=100)
user_name = models.CharField(max_length=80)
pub_date = models.DateField()
class Moment(MessageBase):
headline = models.CharField(max_length=50)
class Coment(MessageBase):
level = models.CharField(max_length=1, choices=LEVELS)
迁移数据后,会定义三个数据表:
数据表 Moment:有id、headline
数据表 Comment:有id、level
数据表 MessageBase:有id、content、user_name、pub_date
PS:在子类实例中可以通过小写的父类的名字可以引用父类的实力
m1 = Moment(user_name='Terry', headline='Hello World')
print m1.messagebase.user_name
3、代理模型继承:父类用于在底层数据库中管理数据表,而子类不定义数据列,只定义查询数据集的排序方式等元数据
from django.db import models
class Moment(models.Model):
id = models.AutoField()
headline = models.CharField(max_length=50)
content = models.CharField(max_length=100)
user_name = models.CharField(max_length=80)
pub_date = models.DateField()
class OrderedMoment(Moment):
class Meta:
proxy = True
ordering = ['-pub_date']
使用代理模型继承的原因是子类中新的特性不会影响父类模型及其已有代码的行为