Django模型
模型是你的数据的唯一的、权威的信息源。它包含你所储存数据的必要字段和行为。通常,每个模型对应数据库中唯一的一张表。
1.基础
- 每个模型都是django.db.models.Model 的一个Python 子类。
- 模型的每个属性都表示为数据库中的一个字段。
- Django 提供一套自动生成的用于数据库访问的API;
2.简单例子
定义了一个UserMessage模型(相当于数据库中的一张表),它有5个属性(相当于数据库中的字段)。每个字段都被指定成一个类属性,每个属性映射到一个数据库的列。
class UserMessage(models.Model): # 自动生成一个ID主键 object_id = models.CharField(max_length=20, primary_key=True, default='', verbose_name=u"主键") name = models.CharField(max_length=20,verbose_name=u"用户名") email = models.EmailField(verbose_name=u"邮箱") address = models.CharField(max_length=100,verbose_name=u"邮箱") message = models.CharField(max_length=500,verbose_name="留言")
上述创建过程,相当于数据创建表的过程,如下:
CREATE TABLE UserMessage ( object_id INT(20) PRIMARY KEY, name varchar(20) NOT NULL, email varchar(30) NOT NULL address varchar(100) NOT NULL email varchar(50) NOT NULL );
注:如果没有定义主键,Django会默认生成一个id字段的作为主键。
3.使用模型
定义好模型之后,接下来你需要告诉Django 使用这些模型。你要做的就是修改配置文件中的INSTALLED_APPS 设置,在其中添加models.py所在应用的名称。
具体路径:settings--->INSTALLED_APPS------>'message'
上述操作完成后,先执行manage.py makemigrations给应用生成迁移脚本,然后执行manage.py migrate。
makemigrations 命令负责保存你的模型变化到一个迁移文件 - 和 commits很类似 - 同时 migrate负责将改变提交到数据库。
4.字段
对于一个模型来说,最重要的和不可或缺的是列出该模型在数据库中定义的字段。字段由models类属性指定。要注意选择的字段名称不要和模型 API 冲突,比如clean、save 或者delete。
例如:
from django.db import models class Musician(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) instrument = models.CharField(max_length=100) class Album(models.Model): artist = models.ForeignKey(Musician) name = models.CharField(max_length=100) release_date = models.DateField() num_stars = models.IntegerField()
5.字段类型
模型中的每个字段都是 Field 子类的某个实例。Django 自带数十种内置的字段类型;
6.字段的自述名
除ForeignKey、ManyToManyField 和 OneToOneField 之外,每个字段类型都接受一个可选的位置参数(在第一的位置) —— 字段的自述名。如果没有给定自述名,Django 将根据字段的属性名称自动创建自述名 —— 将属性名称的下划线替换成空格。
在这个例子中,自述名是 "person's first name":
first_name = models.CharField("person's first name", max_length=30)
在这个例子中,自述名是 "first name":
first_name = models.CharField(max_length=30)
ForeignKey、ManyToManyField 和 OneToOneField 都要求第一个参数是一个模型类,所以要使用 verbose_name 关键字参数才能指定自述名:
poll = models.ForeignKey(Poll, verbose_name="the related poll") sites = models.ManyToManyField(Site, verbose_name="list of sites") place = models.OneToOneField(Place, verbose_name="related place")
7.关系
Django 提供了三种最常见的数据库关系:多对一(many-to-one),多对多(many-to-many),一对一(one-to-one)。
-
多对一关系
Django 使用 django.db.models.ForeignKey 定义多对一关系。和使用其它字段类型一样:在模型当中把它做为一个类属性包含进来。
ForeignKey 需要一个位置参数:与该模型关联的类。
比如,一辆汽车(Car)有一个制造商(Manufacturer) —— 但是一个制造商(Manufacturer) 生产很多汽车(Car),每一辆汽车(Car) 只能有一个制造商(Manufacturer) —— 使用下面的定义:
from django.db import models class Manufacturer(models.Model): # ... pass class Car(models.Model): manufacturer = models.ForeignKey(Manufacturer) # 一对多的关系,外键放在多的一方 # ... 可以设置第二个参数verbose_name="related place"
多对一实例:
from django.db import models class Reporter(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) email = models.EmailField() def __str__(self): # __unicode__ on Python 2 return "%s %s" % (self.first_name, self.last_name) class Article(models.Model): headline = models.CharField(max_length=100) pub_date = models.DateField() reporter = models.ForeignKey(Reporter) def __str__(self): # __unicode__ on Python 2 return self.headline class Meta: ordering = ('headline',)
-
多对多关系
ManyToManyField 用来定义多对多关系,用法和其他Field 字段类型一样:在模型中做为一个类属性包含进来。
ManyToManyField 需要一个位置参数:和该模型关联的类。
例如,一个披萨可以有多种馅料 ,一种馅料 也可以位于多个披萨上。 如下展示:
from django.db import models class Topping(models.Model): # ... pass class Pizza(models.Model): # ... toppings = models.ManyToManyField(Topping)
建议你以被关联模型名称的复数形式做为ManyToManyField 的名字(例如上例中的toppings)。
在哪个模型中设置 ManyToManyField 并不重要,在两个模型中任选一个即可 —— 不要两个模型都设置。
应用实例:
from django.db import models class Publication(models.Model): title = models.CharField(max_length=30) def __str__(self): # __unicode__ on Python 2 return self.title class Meta: ordering = ('title',) class Article(models.Model): headline = models.CharField(max_length=100) publications = models.ManyToManyField(Publication) def __str__(self): # __unicode__ on Python 2 return self.headline class Meta: ordering = ('headline',)
有些情况下,Django 允许你指定一个中介模型来定义多对多关系。 你可以将其他字段放在中介模型里面。源模型的ManyToManyField 字段将使用through 参数指向中介模型。对于上面的音乐小组的例子,代码如下:
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)
在设置中介模型时,要显式地指定外键并关联到多对多关系涉及的模型。这个显式声明定义两个模型之间是如何关联的。
中介模型有一些限制:
- 中介模型必须有且只有一个外键到源模型(上面例子中的Group),或者你必须使用ManyToManyField.through_fields 显式指定Django 应该在关系中使用的外键。如果你的模型中存在不止一个外键,并且through_fields没有指定,将会触发一个无效的错误。 对目标模型的外键有相同的限制(上面例子中的 Person)。
- 对于通过中介模型与自己进行多对多关联的模型,允许存在到同一个模型的两个外键,但它们将被当做多对多关联中一个关系的两边。如果有超过两个外键,同样你必须像上面一样指定through_fields,否则将引发一个验证错误。
- 使用中介模型定义与自身的多对多关系时,你必须设置 symmetrical=False.
-
一对一关系
OneToOneField用来定义一对一关系。 用法和其他字段类型一样:在模型里面做为类属性包含进来。
当某个对象想扩展自另一个对象时,最常用的方式就是在这个对象的主键上添加一对一关系。
OneToOneField要一个位置参数:与模型关联的类。
8.字段名限制
Django 对字段的命名只有两个限制:
字段的名称不能是Python 保留的关键字,因为这将导致一个Python 语法错误。
class Example(models.Model): pass = models.IntegerField() # 'pass' is a reserved word!
由于Django 查询语法的工作方式,字段名称中连续的下划线不能超过一个。
class Example(models.Model): foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
9.Meta的使用
from django.db import models class UserMessage(models.Model): # 自动生成一个ID主键 object_id = models.CharField(max_length=20, primary_key=True, default='', verbose_name=u"主键") name = models.CharField(max_length=20,verbose_name=u"用户名") email = models.EmailField(verbose_name=u"邮箱") address = models.CharField(max_length=100,verbose_name=u"邮箱") message = models.CharField(max_length=500,verbose_name="留言") class Meta: # 元信息使用 verbose_name = u"用户留言信息" ordering = ["name"] # 按照名字排序 db_table = "userinfo"
模型元数据是“任何不是字段的数据”,比如排序选项(ordering),数据库表名(db_table)或者人类可读的单复数名称(verbose_name 和verbose_name_plural)。在模型中添加class Meta是完全可选的,所有选项都不是必须的。
模型元
abstract = True, 就表示模型是 抽象基类 (abstract base class) db_table = 'music_album' 数据表的名称,在 MySQL中使用小写字母为表命名 ordering = ['-order_date'] 每个字符串是一个字段名,前面带有可选的“-”前缀表示倒序。前面没有“-”的字段表示正序。使用"?"来表示随机排序。 ordering = ['pub_date'] 正序排序 ordering = ['-pub_date'] 倒序排序 ordering = ['-pub_date', 'author'] 先按照pub_date的倒序排序,再按照 author 的正序排序 verbose_name = "pizza" 对象的一个易于理解的名称,为单数;如果此项没有设置,Django会把类名拆分开来作为自述名,比如CamelCase 会变成camel case verbose_name_plural = "stories" 对象复数形式的名称;如果此项没有设置,Django 会使用 verbose_name + "s"。
10.模型的方法
可以在模型上定义自定义的方法来给你的对象添加自定义的“底层”功能。Manager 方法用于“表范围”的事务,模型的方法应该着眼于特定的模型实例。
这是一个非常有价值的技术,让业务逻辑位于同一个地方 —— 模型中。
例如,下面的模型具有一些自定义的方法:
from django.db import models class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) birth_date = models.DateField() def baby_boomer_status(self): "Returns the person's baby-boomer status." import datetime if self.birth_date < datetime.date(1945, 8, 1): return "Pre-boomer" elif self.birth_date < datetime.date(1965, 1, 1): return "Baby boomer" else: return "Post-boomer" def _get_full_name(self): "Returns the person's full name." return '%s %s' % (self.first_name, self.last_name) full_name = property(_get_full_name)
更多相关信息参考:http://python.usyiyi.cn/translate/django_182/topics/db/models.html