1. 模型示例代码
from django.db import models
from django.urls import reverse
# 自定义Manager方法
class HighRatingManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(rating=1)
# CHOICES选项
# choice这个属性,用来限制用户做出选择的范围
class Rating(models.IntegerChoices):
VERYGOOD = 1, 'Very Good'
GOOD = 2, 'Good'
BAD = 3, 'Bad'
class Product(models.Model):
# 数据表字段
name = models.CharField('name', max_length=30)
rating = models.IntegerField(max_length=1, choices=Rating.choices)
# MANAGERS方法
objects = models.Manager()
high_rating_products =HighRatingManager()
# META类选项
class Meta:
verbose_name = 'product'
verbose_name_plural = 'products'
# __str__方法
def __str__(self):
return self.name
# 重写save方法
def save(self, *args, **kwargs):
do_something()
super().save(*args, **kwargs)
do_something_else()
# 定义单个对象绝对路径
def get_absolute_url(self):
return reverse('product_details', kwargs={'pk': self.id})
# 其它自定义方法
def do_something(self):
from django.db import models
# 可在主项目文件添加 base_model.py
class BaseModel(models.Model):
'''模型抽象基类'''
create_time= models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
update_time= models.DateTimeField(auto_now=True, verbose_name="更新时间")
is_delete= models.BooleanField(default=False, verbose_name="删除标记")
class Meta:
abstract= True #说明是一个抽象模型类
2. 说明
- 每个Django的模型(model)实际上是个类,继承了models.Model。每个Model应该包括属性(字段),关系(比如单对单,单对多和多对多)和方法
- 定义好Model模型后,Django的接口会自动帮你在数据库生成相应的数据表
- python manage.py makemigrations和python manage.py migrate两个命令,前者检查模型有无变化,后者将变化迁移至数据表。之后,Django会在数据库中生成或变更由appname_modelname组成的数据表
在定义模型需要明确的是:
- 这个Field是否有必选项
- 比如 CharField 的 max_length 和 ForeignKey 的 on_delete 选项是必须要设置的
- 这个Field是否必需
- blank = True or False
- 是否可以为空
- null = True or False
3. 组成
Django模型分别由模型字段、META选项和方法三部分组成。一般编写顺序如下:
- 定义的模型字段:包括基础字段和关系字段
- 自定义的Manager方法:改变模型
- class Meta选项: 包括排序、索引等等(可选)。
- def str():定义单个模型实例对象的名字(可选)。
- def save():重写save方法(可选)。
- def get_absolute_url():为单个模型实例对象生成独一无二的url(可选)
- 其它自定义的方法。
1. 模型的字段
1. 基础字段
- CharField()
- 最大字符长度,设置 max_length = xxx
- 该字段不是必填项,设置 blank = True,default = “”
- 唯一,设置 unique = True
- choice选项,设置 choices = XXX_CHOICES
- TextField()
- 适合大量文本
- 最大字符长度,设置 max_length = xxx
- DateField() 、 DateTimeField()
- 默认日期和时间,设置 default = xxx
- 对于DateTimeField,先要from django.utils import timezone,才可设置 default = timezone.now
- 自动记录一次修改日期(modified),设置 auto_now = True
- 自动记录创建日期(created),设置 auto_now_add = True
- EmailField()
- 一般Email用于用户名应该是唯一的,建议设置 unique = True
- IntegerField() 、 SlugField()
- 设置 blank = True or null = True
- URLField() 、 BooleanField()
- BooleanField一般建议设置 defaut = True or False
- FileField()
- 文件字段
- 上传文件夹路径,设置 upload_to = “/some folder/”
- 文件最大长度,设置 max_length = xxxx
- ImageField()
- 同上
2. 关系字段
-
OneToOneField(to, on_delete=xxx, options)
- 单对单关系
- to 必须指向其他模型
- 必需指定 on_delete 选项
- 便于反向查询,设置 related_name = xxx
-
ForeignKey(to, on_delete=xxx, options)
- 单对多关系
- to 必须指向其他模型
- 必需指定 on_delete 选项
- 便于反向查询,设置 related_name = xxx
- 可设置 default = xxx 、 null = True 、limit_choices_to =
-
ManyToManyField(to, options)
- 单对多关系
- to 必须指向其他模型
- 便于反向查询,设置 related_name = xxx
- 表示多对多关系不是对称的,设置 symmetrical = False
- 建立中间模型来搜集更多信息,设置 through = 'intermediary model
- 示例如下:一个人加入多个组,一个组包含多个人,我们需要额外的中间模型记录加入日期和理由
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)
- 选项 on_delete
- on_delete = models.CASCADE or on_delete = models.SET_NULL
可填 | 作用 | 说明 |
---|---|---|
CASCADE | 级联删除 | 与之关联的另一个表数据都会被删除 |
PROTECT | 保护模式 | 如果有外键关联,就不允许删除,删除的时候会抛出ProtectedError错误,除非先把关联了外键的记录删除掉 |
SET_NULL | 置空模式 | 删除的时候,外键字段会被设置为空 |
SET_DEFAULT | 置默认值 | 删除的时候,外键字段设置为默认值 |
SET() | 自定义一个值 | 删除的时候,外键字段设置为自定义值 |
DO_NOTHING | 什么也不做 | 删除不报任何错,外键值依然保留,但是无法用这个外键去做查询 |
- 选项 related_name
- related_name 用于设置模型反向查询的名字
- 反向查询:一个书籍表,一个出版商表,书籍表中带有一个字段“出版商名字”,但没有具体其他的信息
3. 模型的META选项
参数 | 作用 |
---|---|
abstract = True | 指定该模型为抽象模型 |
proxy = True | 指定该模型为代理模型 |
verbose_name = xxx | 为模型设置便于人类阅读的别名 |
verbose_name_plural = xxx | 为模型设置便于人类阅读的别名 |
db_table = xxx | 自定义数据表名 |
odering = [’-pub-date’] | 自定义按哪个字段排序,-代表逆序 |
permissions=[] | 为模型自定义权限 |
managed=False | 默认为True,若为False,则不会为这个模型生成数据表 |
indexes = [] | 为数据表设置索引,对于频繁查询的字段,建议设置索引 |
constraints= | 给数据库中的数据表增加约束 |
2. 模型的方法
1. 标椎方法
方法 | 作用 |
---|---|
def __str__() | 给单个模型对象实例设置人为可读的名字(可选) |
def save() | 重写save方法(可选) |
def get_absolute_url() | 为单个模型实例对象生成独一无二的url(可选) |
2. 自定义方法
# 为每篇文章生成独一无二的url
def get_absolute_url(self):
return reverse('blog:article_detail', args=[str(self.id)])
# 计数器
def viewed(self):
self.views += 1
self.save(update_fields=['views'])
# First, define the Manager subclass.
class DahlBookManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(author='Roald Dahl')
# Then hook it into the Book model explicitly.
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
objects = models.Manager() # The default manager.
dahl_objects = DahlBookManager() # The Dahl-specific manager.