人生苦短
我用Python

Django014-数据模型Model

Django014-数据模型Model

1. 模型简介

模型是Django中非常重要的部分,对应数据库的操作—ORM(关系对象映射,Object Relational Mapping)。

models.py中,每个模型的类都是django.db.models.Model的子类,每一个类表示一个数据库的表,每一个属性表示数据库中的字段。

如下实例:

from django.db import models

class UserInfo(models.Model):
username = models.CharField(max_length=32, unique=True)
password = models.CharField(max_length=32)

def __str__(self):
return self.username

对应的数据库命令:

CREATE TABLE UserInfo(
"id" serial not null primary key,
'username' varcahr(32) not null,
'password' varchar(32) not null
);
  1. 其中自增ID,Django自动为我们创建,也可以手动创建nid = models.AutoField(primary_key=True)
  2. 模型中的类名就是数据库的表名
  3. Django会根据数据库的类型来使用相应的SQL语句

2. 模型使用

2.1 注册应用

定义好模型后,我们需要将应用在Django中进行注册,也就是在settings.py配置文件中添加应用名称,以便于程序能加载到:

INSTALLED_APPS = (
#...
'myapp', #项目名称
#...
)

在用模型创建数据库表及相应的关系之前,先来学习一下基本知识点:

常用字段(模型的属性)

这里所说的字段是针对哦数据库而言,对应模型中的属性。

字段的名称应该注意到:不要和模型API中的名称冲突!

字段类型

常用:

1. models.AtuoField() 自增列,若不写Django自动添加,若要自定义自增列,必须设置为主键primary_key=True
2. BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True

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

class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32)

class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)

3. models.CharField() 字符串字段,必填参数max_length,在数据层和表单验证中均起作用,用来限定字段的长度
4. models.IntegerField() 整型
5. models.BigIntegerField() 长整型
对应的变化范围:
integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }

#自定义无符号整数字段

class UnsignedIntegerField(models.IntegerField):
def db_type(self, connection):
return 'integer UNSIGNED'

PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',

6. models.FloatField() 浮点型
7. models.BooleanField() 布尔型=tinyint(1),不能为空 Blank=True
8. NullBooleanField(Field):
- 可以为空的布尔值
9. TextField(Field)
- 文本类型

10. EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制

11. IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制

12. GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"

13. URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL

14. SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)

15. CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字

16. UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证

17. FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹

18. FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage

19. ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串)

20. DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

21. DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD

22. TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]]

23. DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

24. FloatField(Field)
- 浮点型

25. DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度

26. BinaryField(Field)
- 二进制类型

字段选项(参数)

1、null=True
  数据库中字段是否可以为空
2、primary_key = False
  主键,对AutoField设置主键后,就会代替原来的自增 id 列
3、auto_now 和 auto_now_add
  auto_now 自动创建---无论添加或修改,都是当前操作的时间
  auto_now_add 自动创建---永远是创建时的时间
4、choices 性别选择常用
GENDER_CHOICE = (
(u'M', u'Male'),
(u'F', u'Female'),
)
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
5、max_length
6、default  默认值
7、name|db_column  数据库中字段的列名
8、unique=True  不允许重复,自建索引
9、db_index = True  数据库索引
10、editable=True  在Admin里是否可编辑
11、error_messages=None  错误提示
12、auto_created=False  自动创建
13、upload-to 上传到哪个位置,更多与image,filepath配合使用

#Admin相关
1、blank=True
  django的 Admin 中添加数据时是否可允许空值
2、help_text  在Admin中提示帮助信息
3、blank Admin中是否允许用户输入为空
4、editable Admin中是否可以编辑
5、verbose_name  Admin中字段的显示名称
6、 error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'}
7、validators=[]
自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
)

元信息

class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)
class Meta:
# 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
db_table = "table_name"

# 联合索引
index_together = [
("pub_date", "deadline"),
]

# 联合唯一索引
unique_together = (("driver", "restaurant"),)

# admin中显示的表名称
verbose_name

# verbose_name加s
verbose_name_plural

更多:https://docs.djangoproject.com/en/1.10/ref/models/options/
注:
1.触发Model中的验证和错误提示有两种方式:
a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息
b. 调用Model对象的 clean_fields 方法,如:
# models.py
class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)

email = models.EmailField(error_messages={'invalid': '格式错了.'})

# views.py
def index(request):
obj = models.UserInfo(username='11234', email='uu')
try:
print(obj.clean_fields())
except Exception as e:
print(e)
return HttpResponse('ok')

# Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。

2.Admin中修改错误提示
# admin.py
from django.contrib import admin
from model_club import models
from django import forms


class UserInfoForm(forms.ModelForm):
username = forms.CharField(error_messages={'required': '用户名不能为空.'})
email = forms.EmailField(error_messages={'invalid': '邮箱格式错误.'})
age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'})

class Meta:
model = models.UserInfo
# fields = ('username',)
fields = "__all__"


class UserInfoAdmin(admin.ModelAdmin):
form = UserInfoForm

admin.site.register(models.UserInfo, UserInfoAdmin)

连表关系

Django提供了常见的连表关系:

  • 多对一(many-to-one
  • 多对多(many-to-many
  • 一对一(one-to-one

简单应用场景

  • 多对一:单选下拉框

    如:创建用户信息时,需要选择一个用户类型【普通用户】【金牌用户】【银牌用户】

  • 多对多:多选下拉框

    如:创建用户信息,需要为用户提供多个爱好

  • 一对一:信息记录

    如:一般用于某张表的补充,用户信息是一张表,但并非每一个用户都需要有登录的权限,不需要记录用户名和密码,此时,合理的做法就是新建一张记录登录信息的表,与用户进行一对一的关联,可以方便的从子表查询母表信息或反向查询

其实,一对一,多对多的关系是由多对一衍生而来的,缕清这些关系,只要从多对一入手即可!

实例:

from django.db import models

# Create your models here.

class Colors(models.Model):
colors=models.CharField(max_length=10) #蓝色
def __str__(self):
return self.colors

class Ball(models.Model):
color=models.OneToOneField("Colors") #与颜色表为一对一,颜色表为母表
description=models.CharField(max_length=10) #描述
def __str__(self):
return self.description

class Clothes(models.Model):
color=models.ForeignKey("Colors") #与颜色表为外键,颜色表为母表
description=models.CharField(max_length=10) #描述
def __str__(self):
return self.description

class Child(models.Model):
name=models.CharField(max_length=10) #姓名
favor=models.ManyToManyField('Colors') #与颜色表为多对多

  1. __str__表示:用一个自段替代类本身作为返回值
  2. 在设置ForeignKey时,参数中第一个参数必须为表名,而且该参数有两种方式:

  1. 加引号:不需要考虑建表顺序(推荐)
  2. 不加引号:必须严格按照建表顺序(主表在前,从表在后—有models.ForeignKey的在后面)

其中,多对多关系表有两种创建方式:

  • 自建式
#自建第三张表
class B2G(models.Model):
boy = models.ForeignKey('Boy')
girl = models.ForeignKey('Girl')

class Boy(models.Model):
name = models.CharField(max_length=32)

class Girl(models.Model):
name = models.CharField(max_length=32)

多对多可以理解为是多对一的组合

  • 自动式
class Boy(models.Model):
name = models.CharField(max_length=32)

class Girl(models.Model):
name = models.CharField(max_length=32)
b2g = models.ManyToMany('Boy')

上面简单的介绍了模型的一些基本知识,现在就该来用模型创建数据库表及对应关系了。

2.2 创建数据库表及对应关系

通过上面的基础知识的学习,现在创建表结构应该比较容易啦!

from django.db import models

class Person(models.Model):
name = models.CharField(max_length=128)

def __str__(self): # __unicode__ on Python 2
return self.name

class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')

def __str__(self): # __unicode__ on Python 2
return self.name

class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)ult=0)

上面是官方文档的一个实例

2.3 迁移、同步数据库

创建完表和关系后,就该将进行如下操作:

python manage.py syncdb

注意:Django 1.7.1及以上的版本需要用以下命令
python manage.py makemigrations
python manage.py migrate

到此,模型的基本操作流程就结束了!至于数据库的表操作将在下面单独进行复述。

分享到:更多 ()