通常每个model都映射到一张单独的表,自定义model的特点:每个model都是一个继承自django.db.models.Model的class每个model的attribute代表一个表的列值model中只包含与表列对应的fielddjango会自动生成访问数据库的api示例代码:fromdjango.dbimportmodelsclassPerson(models.Model):#models是module,CharField是classfirst_name = models.CharField(max_length=30)
last_name= models.CharField(max_length=30)
自动创建数据库表,表名默认为app name_model name,可以重命名自动添加id字段作为主键,此行为也可以改写,相当于执行了id=models.AutoField(PRimary_key=true),如果显示指定了其他列为primary key,则不会自动添加id列每个Model都要有一个primary_key=true的field要通过manage.py migrate命令创建数据库表关于字段(field):每个字段都是Field class的子类对象,Field class是抽象类django通过field的类型确定表列的类型确定用于显示field的html元素有效性判断字段名不能是python保留字,不能带‘--’common filed arguments包括不限于:null:默认是false,如果是true,则在数据库表中存储null值blank:默认是false,如果true,则存放空值choices:可以作为field值的tupledefault:field的默认值,可以是一个值也可以是一个callable objectprimary_key:如果是ture,这个field是model的primary keydb_column:field对应的数据库列名db_index:为这个field创建索引unique:如果是true,field的值必须是唯一的help_text:帮助信息model之间的关系,也是表之间的关系多对一:使用ForeignKey类,可以定义自身对自身的多对一关系#多对一:ForeignKey类fromdjango.dbimportmodelsclassManufacturer(models.Model):#...passclassCar(models.Model):
manufacturer=models.ForeignKey(Manufacturer)#...
对对多:ManyToManyField class,可以定义自身对自身的多对多的关系#多对多:ManyToManyField class,在Topping或者Pizza中定义均可fromdjango.dbimportmodelsclassTopping(models.Model):#...passclassPizza(models.Model):#...toppings = models.ManyToManyField(Topping)
可以使用intermediate model管理多对多关系,指定其他field,示例代码:fromdjango.dbimportmodelsclassPerson(models.Model):
name= models.CharField(max_length=128)def__str__(self):returnself.nameclassGroup(models.Model):
name= models.CharField(max_length=128)#through参数指向的就是intermediate classmembers = models.ManyToManyField(Person, through='Membership')def__str__(self):returnself.nameclassMembership(models.Model):
person=models.ForeignKey(Person)
group=models.ForeignKey(Group)#可以指定其他field 描述两者之间的关系date_joined =models.DateField()
invite_reason= models.CharField(max_length=64)
intermediate class的限制条件:必须包含指向两个关系类的foreignkey自身指向自身的多对多关系,应该设置两个指向同一model的foreignkey自身指向自身的多对多关系,ManyToManyField.symmetrical必须为false一对一:OneToOneField class,可以定义自身指向自身的一对一关系自定义field type:需要继承models.FieldMeta options:使用class Meta为model定义metadata,django已经定义了很多Meta option字段,如ordering:排序字段app_label: app namedb_table:model对应的数据库表名abstract指定该类为抽象类managed:默认为true,django会为model创建数据库表,为false则不会创建proxy:指定proxy modelfromdjango.dbimportmodelsclassOx(models.Model):
horn_length=models.IntegerField()classMeta:#排序字段ordering = ["horn_length"]
verbose_name_plural="oxen"#指定存放model的database tabledb_table="myOx"
Model常用的属性和方法:Model.objects:数据库查询的接口,用于返回model instanceget_absolute_url():生成对象的url,在admin site会使用到重写已定义Model方法,一定要调用基类的该方法,否则会改变默认行为,示例代码:fromdjango.dbimportmodelsclassBlog(models.Model):
name= models.CharField(max_length=100)
tagline=models.TextField()defsave(self, *args, **kwargs):
do_something()#调用基类方法super(Blog, self).save(*args, **kwargs)#Call the "real" save() method.do_something_else()
执行自定义sql语句:语法为Manager.raw(raw_query,params=None,translations=None):#两者效果一样Person.objects.raw('SELECT * FROM myapp_person')
Person.objects.all()
定义抽象类:在Meta class中定义abstract=true,抽象类不能创建数据库表,且抽象类中的字段名与其子类中的字段名不能相同。另外Meta class也可以继承fromdjango.dbimportmodelsclassCommonInfo(models.Model):#...classMeta:
abstract=True
ordering= ['name']classStudent(CommonInfo):#django会自定把abstract设为false,所以Student不是抽象类classMeta(CommonInfo.Meta):
db_table='student_info'
multi-table 继承:子model与父model间通过隐式的OneToOneField关联,每个model对应单独的表。显示的OneToOneField会占用ForeignKey或ManyToManyField默认的related_name值,如果在子类中还要使用ForeignKey或者ManyToManyField需要显示指定related_name的值fromdjango.dbimportmodelsclassPlace(models.Model):
name= models.CharField(max_length=50)
address= models.CharField(max_length=80)classRestaurant(Place):
serves_hot_dogs= models.BooleanField(default=False)
serves_pizza= models.BooleanField(default=False)classSupplier(Place):#需要显示指定related_name参数customers = models.ManyToManyField(Place,related_name='provider')
关于related_name以及relatd objects:如果在一个model中通过ForeignKey,OneToOneField或者ManyToManyField定义了relationship,relationship的另一端就是related objects.model可以直接访问related model,related model通过related_name可以访问model,related_name默认的名字是modelclassname_set,是一个Manager对象,示例代码:fromdjango.dbimportmodelsclassBlog(models.Model):
name= models.CharField(max_length=100)
tagline=models.TextField()def__str__(self):returnself.nameclassEntry(models.Model):#blog 是related objectblog =models.ForeignKey(Blog)
headline= models.CharField(max_length=255)
body_text=models.TextField()
pub_date=models.DateField()def__str__(self):returnself.headline
b= Blog.objects.get(id=1)
b.entry_set.all()#Returns all Entry objects related to Blog.#b.entry_set is a Manager that returns QuerySets.b.entry_set.filter(headline__contains='Lennon')
b.entry_set.count()
要注意的问题:抽象类中定义了relationship时,如果要显示指定related_name,则抽象类的多个子类会都包含相同的related_name会导致错误,正确的方式是在related_name中包含‘%(app_label)s’和’%(class)s’,app_label会用app name替换,class用class name替换fromdjango.dbimportmodelsclassBase(models.Model):
m2m= models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related")classMeta:
abstract=TrueclassChildA(Base):passclassChildB(Base):pass#如果related_name指定了固定名字如"refer",那么m2m.refer无法确定是引用ChildA还是ChildB,如果
#Base类中隐式指定related_name,则不会有错误,ChildA中的related_name默认为childa_set,ChildB中
#related_name默认为childb_set
Proxy models:如果需要改变一个model的behavior,如添加新方法,改变默认的manager等,不需要添加新数据时可以使用proxy model.创建,删除,更新model数据都同使用original model一样会被保存。区别是在proxy model中改变默认的ordering,manager等则不会改变original model. original model的所有实例都可以在Proxy model中访问,反之亦然。对于非抽象model类,proxy model只能继承一个model,对于抽象model类,如果抽象类中没有field则可以继承任意多个model fromdjango.dbimportmodelsclassPerson(models.Model):
first_name= models.CharField(max_length=30)
last_name= models.CharField(max_length=30)classMyPerson(Person):classMeta:#定义proxy model的方法proxy =True
ordering= ["last_name"]defdo_something(self):#...pass#可以在proxy model中访问original model实例,反之亦然p = Person.objects.create(first_name="foobar")
MyPerson.objects.get(first_name="foobar")