# myapp/models.py
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
def __str__(self):
return self.first_name + self.last_name
- Django 会自动添加一个 Primary Key --
id
# mysite/settings.py
INSTALLED_APPS = [
#...
'myapp',
#...
]
步骤:
- 在
myapp/models.py
定义 Model - 在
mysite/settings.py
的INSTALLED_APP
添加 APP -
$ python manage.py makemigrations
(可选) $ python manage.py migrate
Fields
除了表示 Model 之间关系的: ForeignKey
, ManyToManyField
, OneToOneField
之外,其他 Field 都有一个可选的参数(第一位置),用于指定 Field 的名称,如果省略,则与 Field 变量名相同(下划线将被空格替代)
first_name = models.CharField("person's first name", max_length=30) # person's first name
first_name = models.CharField(max_length=30) # first name
- 表示关系的 Field 的第一个参数是 Model Class,所以要指定名称需要使用关键字参数
verbose_name
(值的首字母不要大写,Django将在必要时自动转换)
Field Types
Field Options
Private Options
- model.CharField():
max_length
Public Options
- null: False (数据库)
- blank: False (HTML Form)
- default: value / callable object
- unique
- primary_key = True: 覆盖默认的主键
id
from django.db import models
class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)
>>> fruit = Fruit.objects.create(name='Apple')
>>> fruit.name = 'Pear'
>>> fruit.save()
# 主键是只读的,如果修改主键的值并保存,实际上是新创建一个值
>>> Fruit.objects.values_list('name', flat=True)
<QuerySet ['Apple', 'Pear']>
- choices: 里面包含有个值的元组的一个可迭代对象
YEAR_IN_SCHOOL_CHOICES = (
('FR', 'Freshman'), # (value, 'display text')
('SO', 'Sophomore'),
('JR', 'Junior'),
('SR', 'Senior'),
('GR', 'Graduate'),
)
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)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display() # 查看用于显示的值 get_field_display()
'Large'
Relationships
Many to one: ForeignKeyField
表示多对一的关系,使用: django.db.models.ForeignKey
- 习惯:在子属中定义 ForeignKey
# 一个汽车厂对应多辆汽车
from django.db import models
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
# 习惯:变量名与关联的 Model 相同,使用小写
# ...
Many to Many: ManyToManyField
简单的多对多关系
# 一个披萨上可以放多种配料
# 不同配料可以放在不同披萨上
from django.db import models
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)
# 习惯:用复数的变量名(表示多个对象)
# 只能在任意一个 Model 上定义 ManyToManyField
# 习惯是放在 HTML Form 中占主要的那个
复杂的多对多关系
复杂的多对多关系可能会在多对多的关系上定义额外的属性,因此,可以将 “关系” 写成一个独立的 Model(这个 Model 称为中间Model, intermediate model),通过参数 through
指明
# 乐队与成员之间的关系
# 一个乐队可以拥有多名成员
# 一名音乐家可以加入多个乐队
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership') # through 指明中间 Model
def __str__(self):
return self.name
class Membership(models.Model):
# 用 Foreign 指明两个多对多关系的 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)
# 对于复杂的多对多关系,必须通过建立 中间Model 来建立多对多关系
# 因为 中间Model 还需要额外的信息:date_joined, invite_reason
# 创建两个人物 ringo, paul
>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
# 创建一个乐队 beatles
>>> beatles = Group.objects.create(name="The Beatles")
# ringo 加入 beatles
>>> m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The Beatles>]>
# paul 加入 beatles
>>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason="Wanted to form a band.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>
>>> # add, create, set 仅适用于简单的多对多关系,以下操作无效
>>> # The following statements will not work
>>> beatles.members.add(john)
>>> beatles.members.create(name="George Harrison")
>>> beatles.members.set([john, paul, ringo, george])
>>> # remove 同样无效,应为如果成员不是唯一的(未使用 unique),remove 不知道要移除哪个
>>> # ringo 再次加入乐队
>>> Membership.objects.create(person=ringo, group=beatles,
... date_joined=date(1968, 9, 4),
... invite_reason="You've been gone for a month and we miss you.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo Starr>]>
>>> # This will not work because it cannot tell which membership to remove
>>> beatles.members.remove(ringo)
>>> # 但是可以使用清空操作: clear
>>> # Beatles have broken up 乐队解散
>>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances
>>> # 同时 Membership 将被删除
>>> Membership.objects.all()
<QuerySet []>
- 查询操作跟简单多对多关系一样
# Find all the groups with a member whose name starts with 'Paul'
# 查询一个组:其中有一位称为的名字以 Paul 开头
>>> Group.objects.filter(members__name__startswith='Paul')
<QuerySet [<Group: The Beatles>]>
# Find all the members of the Beatles that joined after 1 Jan 1961
# 查询成员:在 The Beatles 乐队,并且是在 1961 年 1 月 1 日后加入
>>> Person.objects.filter(
... group__name='The Beatles',
... membership__date_joined__gt=date(1961,1,1))
<QuerySet [<Person: Ringo Starr]>
# 查询 关系中的信息 方式一
>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
# 查询 关系中的信息 方式二
>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
One to One: OneToOneField
一对一的关系多用于继承一个 Model,并且 子Model 中将 父Model 作为 Primary Key
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_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
def __str__(self):
return "%s the restaurant" % self.place.name
class Waiter(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
def __str__(self):
return "%s the waiter at %s" % (self.name, self.restaurant)
剩下 https://docs.djangoproject.com/en/2.0/topics/db/models/#models-across-files
网友评论