Django模型实例学习

模型

每一个模型都映射一个数据库表。

使用模型

定义完模型后需要在INSTALLED_APPS中添加models.py文件的模块的名字。

  1. 先数据库迁移:python manage.py makemigrations

  2. 在运行python manage.py migrate

  3. 向INSTALLED_APPS中添加新的应用

INSTALLED_APPS = [
    #...
    'myapp',
    #...
]

初识模型

模型类名不能与 模型API 冲突的名称,如cleansave_delete等。

字段选项

如果为True,则Django将NULL在数据库中存储空值。默认值为False。 避免在CharField字段上设置为True,字符串字段不输入默认为None类型,但是字符串字段如果加上unique=True的约束后在设置null=true就会出异常。

blank

如果为True,则该字段允许为空白。默认值为False

请注意,这与null有所不同。null与数据库完全相关,而blank与验证相关。如果字段包含blank=True,则表单验证将允许输入一个空值。如果字段包含blank=False,则将需要该字段。

choices

该参数接收一个可重复的列表或元组(基本单位为二元组)。如果指定了该参数,在实例化该模型时,该变量只能取选择列表中的值。

一个选项列表:

YEAR_IN_SCHOOL_CHOICES = (
    ('FR', 'Freshman'),
    ('SO', 'Sophomore'),
    ('JR', 'Junior'),
    ('SR', 'Senior'),
    ('GR', 'Graduate'),
)

每个二元组的第一个值会储存在数据库中,而第二个值将只会用作显示作用。

要获取该细分二元组中相对应的第二个值,使用get_FOO_display()方法。例如:

>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'

default

该变量的值。可以是一个值或者是一个可调用的对象,如果是个可调用对象,每次实例化模型时都会调用该对象。 默认值必须是是不可变对象。

def contact_default():
    return {"email": "to1@example.com"}

contact_info = JSONField("ContactInfo", default=contact_default)

primary_key

默认false,不设置为true Django会自动添加一个IntegerField的字段为主键。

主键是只可读的,如果修改一个模型实例主键字段相当于创建了一个新的模型实例。

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

unique

默认false, 如果设置为 True,这个字段必须在整个表中保持值唯一。

备注名

除了 ForeignKeyOneToOneField,任何字段类型都接收一个可选的参数 verbose_name,如果未指定该参数值, 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接收到的第一个参数为模型的类名,后边可以添加一个备注名。

poll = models.ForeignKey(
    Poll,
    on_delete=models.CASCADE,
    verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
    Place,
    on_delete=models.CASCADE,
    verbose_name="related place",
)

关联关系

Many-to-one relationships

通过在多的模型字段外键设置多对一关系,需要两个位置参数。

from django.db import models

class Manufacturer(models.Model):
    # ...
    pass

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
Many-to-many relationships

多对多在任何模型中添加ManyToManyField字段都可以,但是只能在一个中设置。

在实例化 ManyToManyField的时候使用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')

    def __str__(self):
        return self.name

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.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The 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()来创建关系,remove方法也同样无法使用。

>>> # The following statements will not work
>>> beatles.members.add(john)
>>> beatles.members.create(name="George Harrison")
>>> beatles.members.set([john, paul, ringo, george])
>>> # 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.objects.all()
<QuerySet []>
One-to-one relationships

一对一关系,必须设置为主键

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)

创建几个地方:

>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
>>> p1.save()
>>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland')
>>> p2.save()

创建一个餐馆,将“父”对象的ID传递为该对象的ID:

>>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
>>> r.save()

餐厅可进入其地点:

>>> r.place
<Place: Demon Dogs the place>

一个可以进入餐厅的地方(如果有的话):

>>> p1.restaurant
<Restaurant: Demon Dogs the restaurant>

p2没有关联餐厅:

>>> from django.core.exceptions import ObjectDoesNotExist
>>> try:
>>>     p2.restaurant
>>> except ObjectDoesNotExist:
>>>     print("There is no restaurant here.")
There is no restaurant here.

可以使用hasattr来避免例外捕获的需要:

>>> hasattr(p2, 'restaurant')
False

使用赋值符号来设置地方。因为地方是餐厅的主键,保存将创建一个新的餐厅:

>>> r.place = p2
>>> r.save()
>>> p2.restaurant
<Restaurant: Ace Hardware the restaurant>
>>> r.place
<Place: Ace Hardware the place>

再次设置地方,使用相反方向的赋值:

>>> p1.restaurant = r
>>> p1.restaurant
<Restaurant: Demon Dogs the restaurant>

请注意,必须先保存一个对象,然后才能将其分配给一对一关系。例如,Restaurant使用未保存的Place 加注创建一个ValueError

>>> p3 = Place(name='Demon Dogs', address='944 W. Fullerton')
>>> Restaurant.objects.create(place=p3, serves_hot_dogs=True, serves_pizza=False)
Traceback (most recent call last):
...
ValueError: save() prohibited to prevent data loss due to unsaved related object 'place'.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一切如来心秘密

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值