模型准确且唯一的描述了数据。它包含您存储的数据的重要字段和行为。一般来说,每一个模型都映射一张数据库表。
这个样例定义了一个Person模型,拥有first_name和last_name两个类属性。
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
first_name和last_name是模型的字段,每个字段都被指定为一个类属性,并且每个属性映射为一个数据表列。
上面的Person模型会创建如下一张数据库表:
create table my_model_person
(
id int not null primary key generated by default as identity,
first_name varchar(30) not null,
last_name varchar(30) not null
);
一旦你定义了你的模型,你需要告诉Django你准备使用这些模型了。需要修改设置文件中的INSTALLED_APPS,在这个设置中添加包含models.py文件的模块名称
INSTALLED_APPS = [
...
"myapp"
...
]
如果使用的不是默认的是Mysql数据库还需要在设置中修改DATABASES
DATABASES = {
'default': {
# django数据库引擎
'ENGINE': 'django.db.backends.mysql',
# 数据库名
'NAME': 'you_database_name',
# 用户名
'USER': 'root',
# 登录密码
'PASSWORD': '123456',
# 数据库ip
'HOST': 'localhost',
# 端口
'POST': '3306'
}
}
添加结束后进行数据库的迁移
# 检查app下migrations和models是否有更新
python manage.py makemigrations
# 执行修改
python manage.py migrate
模型中最重要且唯一必要的是数据库的字段定义。字段在类属性中定义。定义字段名时要避免使用与模型API
冲突的名称,例如:
clean,save,delete等。
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
模型中每一个字段都对应时某个Field类的实例,Django利用这些字段来实现对数据库的操作:
每一种字段都需要指定一些特定的参数。例如 CharField
需要接受一个max_length
参数,用以指定数据库存储VARCHAR
数据时用的字节数
一些可选参数是通用的,可用于任何类型的字段
例如
from django.db import models
class Person(models.Model):
SHIRT_SIZES = [
('S', "Small"),
('M', "Medium"),
('L', "Large")
]
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES, null=True)
打开交互测试环境:python manage.py shell
from my_model.models import Person
p = Person(first_name="z",last_name="zj",shirt_size="M")
p.save()
p.shirt_size
'M'
p.get_shirt_size_display()
'Medium'
如果设置为True,将该字段设置为该模型的主键
主键为只可读
,如果你修改一个记录的主键并保存,这等同于你创建了一个新的记录。
class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)
from my_model.models import Fruit
fruit = Fruit(name="1")
fruit.save()
fruit.name
'1'
fruit.name = "2"
fruit.save()
fruit.name
'2'
Fruit.objects.values_list("name",flat=True)
自增主键
class Animal(models.Model):
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=100)
from my_model.models import Animal
# 指定id
a = Animal(id=1,name="dog")
a.name
'dog'
# 不指定id
a = Animal(name="cat")
a.save()
# 从表中拿到所有记录对象
Animal.objects.all()
, ]>
# 从表中拿到所有name的值
Animal.objects.values_list("name")
Animal.objects.values_list("name",flat=True)
# 从表中拿到所有id的值
Animal.objects.values_list("id",flat=True)
# 自增没有问题
first_name = models.CharField("person's first name",max_length=30)
关系型数据库的强大之处在于各个表之间的关联关系。Django提供了定义三种最常见的数据库关联方法:多对一,多对多,一对一
定义一个多对一的关联关系,使用 ForeignKey
class Musician(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
使用shell测试
# 成功保存 create会帮我们直接保存数据
from my_model.models import Musician,Album
m = Musician.objects.create(first_name="1",last_name="2",instrument="3")
a = Album.objects.create(name="4",release_date="2022-10-10",num_stars=5,artist=m)
# 以下操作报错,应为m没有保存就直接作为了a的参数传入
m = Musician(first_name="1",last_name="2",instrument="3")
a = Album(name="4",release_date="2022-10-10",num_stars=5,artist=m)
a.save()
Traceback (most recent call last):
File "", line 1, in
File "C:\Users\g1712\.conda\envs\attend-classclass-begins\lib\site-packages\django\db\models\base.py", line 778, in save
self._prepare_related_fields_for_save(operation_name="save")
File "C:\Users\g1712\.conda\envs\attend-classclass-begins\lib\site-packages\django\db\models\base.py", line 1093, in _prepare_related_fields_for_save
raise ValueError(
ValueError: save() prohibited to prevent data loss due to unsaved related object 'artist'.
# 也可以这样写
m = Musician(first_name="1",last_name="2",instrument="3")
m.save()
a = Album(name="4",release_date="2022-10-10",num_stars=5,artist=m)
a.save()
m = Musician.objects.create(first_name="1",last_name="2",instrument="3")
自关联
公司成员都有上级领导,在prent_id中记录的就是上级领导的id
class Member(models.Model):
member_id = models.AutoField(primary_key=True)
prent_id = models.ForeignKey('self', db_column='prent_id', to_field='member_id', on_delete=models.CASCADE)
披萨、配料对应表
class Pizza(models.Model):
pizza_id = models.AutoField(primary_key=True)
name = models.CharField()
class Topping(models.Model):
topping_id = models.AutoField(primary_key=True)
name = models.CharField()
class PizzaToppingMapping(models.Model):
pizza_topping_mapping_id = models.AutoField(primary_key=True)
pizza_id = models.ForeignKey(Pizza, on_delete=models.CASCADE)
topping_id = models.ForeignKey(Topping, on_delete=models.CASCADE)
使用shell测试
from my_model.models import Pizza,Topping,PizzaToppingMapping
# 添加
p = Pizza.objects.create(name="奥尔良鸡翅烤肉披萨")
t = Topping.objects.create(name="奥尔良鸡翅")
t1 = Topping.objects.create(name="烤肉")
t2 = Topping.objects.create(name="芝士")
pt = PizzaToppingMapping.objects.create(pizza_id=p,topping_id=t)
pt = PizzaToppingMapping.objects.create(pizza_id=p,topping_id=t1)