表结构设计优化
增加普通字段,减少跨表查询带来的性能消耗。
class Article(models.Model):
title = models.CharField(max_length=64, verbose_name='标题')
desc = models.CharField(max_length=256, verbose_name='摘要')
content = models.TextField(verbose_name='文章内容')
publish_time = models.DateTimeField(auto_now_add=True)
# 数据库优化三个字段
up_counts = models.BigIntegerField(verbose_name='点赞数', default=0)
down_counts = models.BigIntegerField(verbose_name='点踩数', default=0)
comment_counts = models.BigIntegerField(verbose_name='评论数', default=0)
# 优化三个字段:up_counts、down_counts、comment_counts
这三个本可以直接跨表查询获取数据,但是为了避免多次跨表查询导致的访问速度慢,
于是采用额外增加三个普通字段,这样就避免了跨表查询的问题;
但是缺点是在使用时需要注意,修改数据需要在代码上保持表之间的同步更新,
choices参数的使用,建立外键关联一对多,自动更新字段,避免直接修改代码
class Course(models.Model):
type_choices = (
(0, 'Python'),
(1, 'Linux'),
)
name = models.CharField(max_length=64)
title = models.CharField(max_length=64)
type = models.IntegerField(choices=type_choices, default=0)
# 此时这个type字段的选项写死了,如果后期需要增加新的课程类型,则需要修改此处的代码,才可以实现新需求
# 其实,可以新建另一张表,课程类型表,采用外键关联的方式,则实现type由数据库驱动时时更新,扩展需求时也不需要修改代码
# 增加新需求时,直接操作数据库,不需要修改代码。
# 优化后的代码
class CourseCategory(BaseModel):
name = models.CharField(max_length=64, unique=True, verbose_name="分类名称")
class Course(BaseModel):
name = models.CharField(max_length=128, verbose_name="课程名称")
# 外键关联
course_category = models.ForeignKey(to="CourseCategory", on_delete=models.SET_NULL,
db_constraint=False, null=True, blank=True,
verbose_name="课程分类"
)
django的ORM跨表查询的两个外键参数:related_name
和related_query_name
-
基于对象的跨表查询,使用
related_name
之后,再跨表就不用使用表名_set
的方式,而是直接使用related_name
指定的字符串 -
related_query_name
,反向查询操作时,使用的连接前缀,用于替换表名
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish = models.ForeignKey(to='Publish', related_name='books') # 一对多,外键关联
authors = models.ManyToManyField(to='Author', related_query_name='u') # 多对多,
# 反向查询,related_name
pub_obj = models.Publish.objects.filter(name='东方出版社').first()
res = pub_obj.book_set.all() # 不用related_name时的写法 book_set
res = pub_obj.books.all() # 使用related_name时的写法 books
# 反向查询,related_query_name
author_obj = models.Author.objects.filter(name='xliu').first()
res = author_obj.u_set.all()