模型
用来构建和管理 Web APP 的数据,根据所定义的类自动生成数据库表。
1. 创建表
from django.db import models
,这个 models 包下有许多类,如 Model、CharField。
有三个东西要注意的:字段、限定字段的参数、修饰表的元类。
from django.db import models
class MyUser(models.Model):
name = models.CharField(max_length=30)
2. 注册模型
如果 models 在目录是 app\models,那么应该在 INSTALLED_APPS
添加 app
。
同时 python manage.py makemigrations (将 Python 代码转换为 SQL 语句)、
python manage.py migrate (执行 SQL 语句)。
3. 字段参数
下面列出所有字段通用、可选、常用的参数。
- null:如果为 True,在数据库中把空值存作 NULL(不是 Python 关键字 None),默认 False 。
- blank:如果为 True,字段允许为空。默认 False。
- blank 为 True,null 值才有意义。null 只与数据库有关,blank 只与类似表格验证有关。
- choices:一个元素都是 tuple 的序列,每个 tuple 由两个元素组成;然后这个序列作为字段的 choices 。
from django.db import models
class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'), // 'S' 存储在数据库,'Small' 在表格部件中显示。
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
# manage.py shell 下测试
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size # 实例属性是数据库中所存储的
'L'
>>> p.get_shirt_size_display() # get_attr_display 是表格部件所显示。
'Large'
- default:默认值或一个可调用对象。如果是可调用对象,它在一个新对象创建时自动调用。
- help_text:帮助信息。
- primary_key:
主键,如果所有字段都不指定其为 True,那么 Django 会自动添加一个IntegerField
字段持有主键。
且主键不可变,更改主键实质是又创建了一个对象。
# models.py
from django.db import models
class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)
# manage.py shell
>>> fruit = Fruit.objects.create(name='Apple') # 等价 fruit = Fruit(name='Apple')、fruit.save()
>>> fruit.name = 'Pear'
>>> fruit.save()
>>> Fruit.objects.values_list('name', flat=True)
<QuerySet ['Apple', 'Pear']>
- unique:唯一。
4. 更详细的字段名
每个字段,第一个可选的位置参数 verbose_name
,默认是字段名。可以自定义:
如 first_name = models.CharField("person's first name", max_length=30)
。
在 ForeignKey、ManyToManyField、OneToOneField 中,
由于第一个位置参数是一个关联的模型类,所以使用关键字参数传入。
如 sites = models.ManyToManyField(Site, verbose_name="list of sites")
5. 表间关系
a. 多对一
使用 models.ForeignKey 。 举个栗子,一辆车只生产于一个制造商,一个制造商生产多种车。
from django.db import models
class Manufacturer(models.Model):
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
b. 多对多
使用 models.ManyToManyField 。举个栗子,一种披萨有多种配料,一种配料可用于多种披萨。
之所以把 ManyToManyField 字段放在 Pizza 而不是 Topping,是因为更符合人的思维:一种披萨有多种配料。
from django.db import models
class Topping(models.Model):
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping) # 字段最好是复数形式
再举一个栗子,一个音乐家属于多个组,一个组有多个音乐家,除了这从属关系之外,还想要得二者之间更详细的信息,如音乐家加入组的时间,就必须创建一个中间模型。通过 ManyToManyField 的 through 参数指定。
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
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)
创建多对多之间的关系,就是创建中间模型的实例。
>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles, # 创建实例
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.")
c. 一对一
使用 OneToOneField,避免在不同模型出现重复字段,也避免了继承。通常用作主键。
举个栗子,一间餐厅对应一个地方。
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
def __str__(self):
return "%s the place" % self.name
class Restaurant(models.Model):
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
primary_key=True,
)
serves_pizza = models.BooleanField(default=False)
def __str__(self):
return "%s the restaurant" % self.place.name
# manage.py shell
>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
>>> p1.save()
>>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland')
>>> p2.save()
>>> r = Restaurant(place=p1, serves_pizza=False)
>>> r.save()
>>> r.place
<Place: Demon Dogs the place>
>>> p1.restaurant # Place 类并没有 restaurant 属性,也可以用
<Restaurant: Demon Dogs the restaurant>
6. 内部元类
用来控制整个模型的行为。
from django.db import models
class Ox(models.Model):
horn_length = models.IntegerField()
class Meta:
ordering = ["horn_length"]
参考文档:
https://docs.djangoproject.com/en/2.0/topics/db/models/#module-django.db.models