整理记录一下Django的Model相关内容,工作中实际用到的点其实不是非常多,但是可以对于Model的一些特性做一些记录,也许长久会发现一些比较好的方式来做同样的事情。
一、Basic:
1、每个model 是 django.db.models.Model 的子类
来自 <https://docs.djangoproject.com/en/1.11/topics/db/models/>
2、每个model 的属性代表一个数据库字段
3、Django 提供一个自动生成的数据库访问API(ORM),
来自 <https://docs.djangoproject.com/en/1.11/topics/db/models/>
二、创建实例
1 2 3 4 5 | from django.db import models
class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) |
来自 <http://tool.oschina.net/highlight>
上述代码实现定义了一个Person,包含first_name和last_name
相对应的数据库表的创建如下:
1 2 3 4 5 | CREATE TABLE myapp_person ( "id" serial NOT NULL PRIMARY KEY, "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL ); |
来自 <http://tool.oschina.net/highlight>
其中:创建的表名带了app的名字,且全为小写。 默认带了一个主键id。
三、使用
1、需要在setting文件中的 INSTALLED_APPS 下新增 app的名称
当新增了app之后,需要执行:
manage.py migrate
也可以先执行
manage.py makemigrations 进行数据迁移
数据库字段都是通过类属性来确定,字段名称不要与models API冲突,比如cleansave等
四、字段选项
choices:
1 2 3 4 5 6 7 8 9 10 | from django.db import models
class Person(models.Model): SHIRT_SIZES = ( ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ) name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES) |
来自 <http://tool.oschina.net/highlight>
1 2 3 4 5 6 | >>> p = Person(name="Fred Flintstone", shirt_size="L") >>> p.save() >>> p.shirt_size 'L' >>> p.get_shirt_size_display() 'Large' |
来自 <http://tool.oschina.net/highlight>
数据库存储第一列的数据,想要获取字段展示的值,使用get_FOO_display() ,这里FOO指的就是choice数据的名称
primary_key:
如果primary_ket=True, 这个字段就是主键。如果未指定,django会自动生成一个IntegerField作为主键
自动生成的主键字段(自增主键),django默认给每个models使用下面语句分配主键
1 | id = models.AutoField(primary_key=True) |
来自 <http://tool.oschina.net/highlight>
字段自述名 (verbose name):
除了ForeignKey,ManyToManyField,OneToOneField,以外的所有字段类型都使用一个参数作为字段自述名的位置参数。如果未命名,则默认为字段的属性名(变量名)将下划线换成空格显示。
positional argument
1 | first_name = models.CharField("person's first name", max_length=30) |
来自 <http://tool.oschina.net/highlight>
verbose name为 person's first name
1 | first_name = models.CharField(max_length=30) |
来自 <http://tool.oschina.net/highlight>
verbose name为 first name
ForeignKey,ManyToManyField,OneToOneField 需要第一个参数必须为模型类(model class),所以使用verbose_name关键字参数指定。
五、跨文件模型
使用其他app的models,只需要在当前models文件顶部引用其他models
Meta 选项:
一般用于 任何不是字段的数据,比如排序(ordering) 数据库表名 ( db_table )。。 可选项,非必须项。排序会增加数据库的开销
1 2 3 4 5 6 7 8 | from django.db import models
class Ox(models.Model): horn_length = models.IntegerField()
class Meta: ordering = ["horn_length"] verbose_name_plural = "oxen" |
来自 <http://tool.oschina.net/highlight>
Model 属性
1、最重要的一个属性就是Manager,是Django模型进行数据查询的接口,用于从数据库获取实例。如果没有定义Manager,则默认名称为objects。 Manager只能通过模型类访问而不能通过模型实例。
定义Manager:
1 2 3 4 5 | from django.db import models
class Person(models.Model): #... people = models.Manager() |
来自 <http://tool.oschina.net/highlight>
如果这样定义之后,使用Person.objects 会出现AtrributeError 异常。但是使用Persoon.people.all()就能获取到Person对象的列表。
未定义则使用默认的objects:Person.objects.all()
六、模型方法
1 2 3 4 5 6 7 8 9 10 | from django.db import models
class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50)
@property def full_name(self): "Returns the person's full name." return '%s %s' % (self.first_name, self.last_name) |
来自 <http://tool.oschina.net/highlight>
full_name 函数就是模型Person的方法,和一般的Python的类方法没什么特殊区别
重写预定义的模型方法:
一些封装好的数据库操作,如果想自定义这些方法,比如save() 或者 delete()
1 2 3 4 5 6 7 8 9 10 | from django.db import models
class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField()
def save(self, *args, **kwargs): do_something() super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. do_something_else() |
来自 <http://tool.oschina.net/highlight>
确保调用super(Blog, self).save(*args, **kwargs) 来完成数据被保存到数据库。如果不调用默认的行为不会发生并且数据库不会被改变
七、模型继承
Django的基础类型必须是 django.db.models.Model 的子类
Django中有三种继承类型:
1、抽象基类(abstract baseclasses) 如果不想在多个子类中重复的保存信息,可以存在父类中;这种类型不会封闭的使用。
2、多表继承(multi-tableinheritance)如果想子类化一个已经存在的模型,并且向每个模型拥有自己的数据表
3、代理模型(proxy models)如果想修改模型的Python层次的行为,并且在任何情况下都不改变模型的字段
抽象基类:
定义抽象基类,设置abstract=True
1 2 3 4 5 6 7 8 9 10 11 | from django.db import models
class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField()
class Meta: abstract = True
class Student(CommonInfo): home_group = models.CharField(max_length=5) |
来自 <http://tool.oschina.net/highlight>
Student模型将会有三个字段:name, age, home_group
抽象基类不能像正常的Django模型那样使用:不会生成数据表,不会有manager,不能被实例化以及直接保存
元类继承:
当抽象基类被创建,Django会把在基类中声明的任何Meta内部类作为一个属性。如果子类没有声明自己的Meta类,将会继承父类的Meta类。如果子类想扩展父类的Meta类,可以在子类中声明创建:
1 2 3 4 5 6 7 8 9 10 11 12 | from django.db import models
class CommonInfo(models.Model): # ... class Meta: abstract = True ordering = ['name']
class Student(CommonInfo): # ... class Meta(CommonInfo.Meta): db_table = 'student_info' |
来自 <http://tool.oschina.net/highlight>