- model是Django中的数据模型
- 每个model都是继承自django.db.models.Model的子类
- 每个model都映射一个数据表
- model中的每个类属性对应着数据表中的一列
- django支持ORM
- 创建model并进行migrate后
- Django会自动生成表名(可以自定义)
- Django会自动增加主键一列(可以自定义)
- Django会根据不同数据库创建不同的SQL语句
-
Field中的常见选项
- null:允许该列数据为空(默认为False)
- blank:主要用于是否允许表单为空(默认为False)
- choices:为一个Field提供可选项(并且默认生成的表单为一个选项)
from django.db import models class Person(models.Model): # choices的对象是一个可迭代对象,其元素为‘含有两个元素的元组’ SHIRT_SIZES = ( ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ) name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES) # choice API >>> p = Person(name="Fred Flintstone", shirt_size="L") >>> p.save() >>> p.shirt_size 'L' >>> p.get_shirt_size_display() # get_FOO_display()方法可以显示具体内容 'Large'
- default:既可以是一个数值对象,也可以是一个可调用对象
- help_text:在生成的表单中展示‘帮助’信息
- primary_key:将某一列设置为主键(该列变为只读);默认为False,即Django会自动创建一个整型主键
- unique:该列中的每个数据必须独一无二(默认为False)
- 自动生成主键
默认情况下,如果不显式指定主键,Django会在model中自动添加以下属性id = models.AutoField(primary_key=True)
- 显式指定列名
对于非关系型列(即非ForeignKeyField,ManyToManyField,OneToOneField),第一个位置参数为空时,将默认属性名为列名;否则使用位置参数作为列名
对于关系型列,需要指定位置参数以表明关联的数据表# 列名为"person's first name" first_name = models.CharField("person's first name", max_length=30) # 列名为"first_name" first_name = models.CharField(max_length=30) # 关联表为"Poll" poll = models.ForeignKey( Poll, on_delete=models.CASCADE, verbose_name="the related poll", )
- 关联
- Many-to-one 关联
使用django.db.models.ForeignKey,第一个位置参数需要指定关联表名 - Many-to-many 关联
使用django.db.models.ManyToManyField(相关的两个表中,只需要在一个表中指定即可)
可以显式的创建many-to-many的关联数据表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) # 通过through指定关联表 members = models.ManyToManyField(Person, through='Membership') def __str__(self): # __unicode__ on Python 2 return self.name class Membership(models.Model): person = models.ForeignKey(Person, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE) date_joined = models.DateField() invite_reason = models.CharField(max_length=64)
- One-to-one 关联
使用django.db.models.OneToOneField,可以用于扩展某一model
- Many-to-one 关联
-
Meta 选项
Model的Meta中保存着所有非列的属性(比如ordering(默认排序)、db_table(数据表名称)等等)from django.db import models class Ox(models.Model): horn_length = models.IntegerField() # class Meta 是可选项 class Meta: ordering = ["horn_length"] verbose_name_plural = "oxen"
- Model 的方法
我们可以在Model中自定义方法,也可以使用或者重载Model中已有的方法
有两个方法在大多数情况下需要我们自己定义- __ str__()
- get_absolute_url()
该方法告诉Django如何得到一个对象的URL(一般使用django的reverse()函数)def get_absolute_url(self): from django.urls import reverse return reverse('people.views.details', args=[str(self.id)])
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() # 关键在于对Model.save()方法的继承上,另外通过使用(*args, **kwargs)参数可以自动获取相关参数 super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. do_something_else()
- Model的继承
django中存在三种继承- Abstract base classes
- Multitable inheritance
- Proxy models
- Abstract base classes
在class Meta中设置abstract = True,就可以将该model变为抽象类——该类中定义的列属性可以被子类所继承而无需重新定义,且class Meta中的属性亦会被继承(除了abstract = True)
Abstract base classes并不会产生数据表,也不能直接用于创建实例
为了指定子类关联表列的relate_name,可以在abc类的关联表列中进行设置from django.db import models class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField() # 将CommonInfo声明为一个abc类 class Meta: abstract = True ordering = ['name'] class Student(CommonInfo): # Student 类自动继承name和age列 home_group = models.CharField(max_length=5) class Meta: # Student 类会继承CommonInfo中的Meta的信息 # 不过在此之前会自动设置abstract=False(当然也可以自己显式地设置abstract=True从而成为abc类) db_table = 'student_info'
# common/models.py from django.db import models class Base(models.Model): m2m = models.ManyToManyField( OtherModel, # 若不设置related_name,则默认为"子类名 + '_set'" # %(app_label)s 指代当前应用名称 # %(class)s 指代当前类的类名 related_name="%(app_label)s_%(class)s_related", related_query_name="%(app_label)s_%(class)ss", ) class Meta: abstract = True # OtherModel 使用 ChildA 类时的属性名将是'common_childa_related' class ChildA(Base): pass class ChildB(Base): pass
- Multi-table inheritance
父类和子类都可以生成数据表,且子类会继承父类的类属性(列属性),但父类和子类是两个不同的表
此外,不同于abc类,子类不会继承父类class Meta中的属性 - Proxy models
Proxy model用于当你只想为一个表增加一些方法或者Meta属性,而不想改变原model的代码时from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) class MyPerson(Person): class Meta: # 指定该类为Person的代理数据模型 proxy = True # 在该proxy model中可以增加一个额外的Meta属性 odering = ['last_name'] # 在该proxy model中可以增加一些额外的方法 def do_something(self): # ... pass # 需要注意的一点是Person和MyPerson类都可以调用Person数据表中的数据 # 不同之处在于通过Person类创建/查找到的实例中没有ordering属性,也不能调用do_something方法