Django 学习笔记

模型

2018-03-24  本文已影响10人  一块大番薯

用来构建和管理 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. 字段参数

下面列出所有字段通用、可选、常用的参数。

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

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

上一篇 下一篇

猜你喜欢

热点阅读