Django -- Model

Model.jpg
# 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',
    #...
]

步骤:

  1. myapp/models.py 定义 Model
  2. mysite/settings.pyINSTALLED_APP 添加 APP
  3. $ python manage.py makemigrations (可选)
  4. $ 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'

common model field option reference

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-one relationship model example.

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.'

Many-to-many relationship model example

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)

One-to-one relationship model example

剩下 https://docs.djangoproject.com/en/2.0/topics/db/models/#models-across-files

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容